From 072cc6d525cafdb123c8529f7c74216411406cc6 Mon Sep 17 00:00:00 2001 From: Lee Salzman Date: Tue, 12 Feb 2008 03:30:52 +0000 Subject: [PATCH] added resetgl command to restart renderer in-game git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@1642 e016b1c5-ed68-44aa-a2f7-31cac88cffde --- source/src/main.cpp | 194 ++++++++++++++++++++++----------- source/src/model.h | 2 + source/src/protos.h | 5 +- source/src/rendergl.cpp | 17 ++- source/src/rendermodel.cpp | 5 + source/src/renderparticles.cpp | 5 + source/src/rendertext.cpp | 7 ++ source/src/texture.cpp | 43 +++++++- source/src/vertmodel.h | 24 ++++ 9 files changed, 229 insertions(+), 73 deletions(-) diff --git a/source/src/main.cpp b/source/src/main.cpp index 5620b0b4..6e3d7b08 100644 --- a/source/src/main.cpp +++ b/source/src/main.cpp @@ -9,7 +9,6 @@ void cleanup(char *msg) // single program exit point; { abortconnect(); disconnect(1); - cleangl(); cleansound(); cleanupserver(); } @@ -154,7 +153,11 @@ void setresdata(char *s, enet_uint32 c) } #endif +#ifdef _DEBUG VARF(fullscreen, 0, 0, 1, setfullscreen(fullscreen!=0)); +#else +VARF(fullscreen, 0, 1, 1, setfullscreen(fullscreen!=0)); +#endif COMMAND(screenres, ARG_2INT); @@ -168,6 +171,125 @@ VARFP(gamma, 30, 100, 300, } }); +void setupscreen(int &usedcolorbits, int &useddepthbits, int &usedfsaa) +{ + int flags = SDL_RESIZABLE; + #if defined(WIN32) || defined(__APPLE__) + flags = 0; + #endif + if(fullscreen) flags |= SDL_FULLSCREEN; + SDL_Rect **modes = SDL_ListModes(NULL, SDL_OPENGL|flags); + if(modes && modes!=(SDL_Rect **)-1) + { + bool hasmode = false; + for(int i = 0; modes[i]; i++) + { + if(scr_w <= modes[i]->w && scr_h <= modes[i]->h) { hasmode = true; break; } + } + if(!hasmode) { scr_w = modes[0]->w; scr_h = modes[0]->h; } + } + bool hasbpp = true; + if(colorbits && modes) + hasbpp = SDL_VideoModeOK(modes!=(SDL_Rect **)-1 ? modes[0]->w : scr_w, modes!=(SDL_Rect **)-1 ? modes[0]->h : scr_h, colorbits, SDL_OPENGL|flags)==colorbits; + + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); +#if SDL_VERSION_ATLEAST(1, 2, 11) + if(vsync>=0) SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, vsync); +#endif + static int configs[] = + { + 0x3, /* try everything */ + 0x2, 0x1, /* try disabling one at a time */ + 0 /* try disabling everything */ + }; + int config = 0, msaabufs = 0, msaasamples = 0; + if(screen) + { + SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &msaabufs); + SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &msaasamples); + } + loopi(sizeof(configs)/sizeof(configs[0])) + { + config = configs[i]; + if(!depthbits && config&1) continue; + if(!fsaa && config&2) continue; + if(depthbits) SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, config&1 ? depthbits : 16); + if(fsaa) + { + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, config&2 ? 1 : msaabufs); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, config&2 ? fsaa : msaasamples); + } + screen = SDL_SetVideoMode(scr_w, scr_h, hasbpp ? colorbits : 0, SDL_OPENGL|flags); + if(screen) break; + } + if(!screen) fatal("Unable to create OpenGL screen"); + else + { + if(!hasbpp) conoutf("%d bit color buffer not supported - disabling", colorbits); + if(depthbits && (config&1)==0) conoutf("%d bit z-buffer not supported - disabling", depthbits); + if(fsaa && (config&2)==0) conoutf("%dx anti-aliasing not supported - disabling", fsaa); + } + + scr_w = screen->w; + scr_h = screen->h; + VIRTW = scr_w*VIRTH/scr_h; + + #ifdef WIN32 + SDL_WM_GrabInput(SDL_GRAB_ON); + #else + SDL_WM_GrabInput(fullscreen ? SDL_GRAB_ON : SDL_GRAB_OFF); + #endif + + usedcolorbits = hasbpp ? colorbits : 0; + useddepthbits = config&1 ? depthbits : 0; + usedfsaa = config&2 ? fsaa : 0; +} + +void resetgl() +{ + loadingscreen(); + + extern void cleanupparticles(); + extern void cleanupmodels(); + extern void cleanuptextures(); + extern void cleanuptmus(); + extern void cleanupgl(); + cleanupparticles(); + cleanupmodels(); + cleanuptextures(); + cleanuptmus(); + cleanupgl(); + c2skeepalive(); + + SDL_SetVideoMode(0, 0, 0, 0); + + int usedcolorbits = 0, useddepthbits = 0, usedfsaa = 0; + setupscreen(usedcolorbits, useddepthbits, usedfsaa); + gl_init(scr_w, scr_h, usedcolorbits, useddepthbits, usedfsaa); + + extern void reloadfonts(); + extern void reloadtextures(); + c2skeepalive(); + if(!reloadtexture(*notexture) || + !reloadtexture("packages/misc/startscreen.png")) + fatal("failed to reload core texture"); + loadingscreen(); + c2skeepalive(); + reloadfonts(); + reloadtextures(); + c2skeepalive(); + preload_playermodels(); + c2skeepalive(); + preload_hudguns(); + c2skeepalive(); + preload_entmodels(); + c2skeepalive(); + preload_mapmodels(); + c2skeepalive(); +} + +COMMAND(resetgl, ARG_NONE); + VARP(maxfps, 5, 200, 500); void limitfps(int &millis, int curmillis) @@ -280,7 +402,7 @@ VARFP(clockfix, 0, 0, 1, clockreset()); int main(int argc, char **argv) { bool dedicated = false; - int fs = SDL_FULLSCREEN, par = 0, uprate = 0, maxcl = DEFAULTCLIENTS, scthreshold = -5, port = 0; + int uprate = 0, maxcl = DEFAULTCLIENTS, scthreshold = -5, port = 0; const char *sdesc = "", *ip = "", *master = NULL, *passwd = "", *maprot = NULL, *adminpwd = NULL, *srvmsg = NULL; #define initlog(s) puts("init: " s) @@ -314,7 +436,7 @@ int main(int argc, char **argv) } break; case 'd': dedicated = true; break; - case 't': fs = 0; break; + case 't': fullscreen = 0; break; case 'w': scr_w = atoi(a); break; case 'h': scr_h = atoi(a); break; case 'z': depthbits = atoi(a); break; @@ -339,9 +461,9 @@ int main(int argc, char **argv) initing = false; initlog("sdl"); + int par = 0; #ifdef _DEBUG par = SDL_INIT_NOPARACHUTE; - fs = 0; #endif if(SDL_Init(SDL_INIT_TIMER|SDL_INIT_VIDEO|par)<0) fatal("Unable to initialize SDL"); @@ -358,75 +480,17 @@ int main(int argc, char **argv) if(SDL_InitSubSystem(SDL_INIT_VIDEO)<0) fatal("Unable to initialize SDL Video"); initlog("video: mode"); - int resize = SDL_RESIZABLE; - #if defined(WIN32) || defined(__APPLE__) - resize = 0; - #endif - SDL_Rect **modes = SDL_ListModes(NULL, SDL_OPENGL|resize|fs); - if(modes && modes!=(SDL_Rect **)-1) - { - bool hasmode = false; - for(int i = 0; modes[i]; i++) - { - if(scr_w <= modes[i]->w && scr_h <= modes[i]->h) { hasmode = true; break; } - } - if(!hasmode) { scr_w = modes[0]->w; scr_h = modes[0]->h; } - } - bool hasbpp = true; - if(colorbits && modes) - hasbpp = SDL_VideoModeOK(modes!=(SDL_Rect **)-1 ? modes[0]->w : scr_w, modes!=(SDL_Rect **)-1 ? modes[0]->h : scr_h, colorbits, SDL_OPENGL|resize|fs)==colorbits; - - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); -#if SDL_VERSION_ATLEAST(1, 2, 11) - if(vsync>=0) SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, vsync); -#endif - static int configs[] = - { - 0x3, /* try everything */ - 0x2, 0x1, /* try disabling one at a time */ - 0 /* try disabling everything */ - }; - int config = 0; - loopi(sizeof(configs)/sizeof(configs[0])) - { - config = configs[i]; - if(!depthbits && config&1) continue; - if(!fsaa && config&2) continue; - if(depthbits) SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, config&1 ? depthbits : 0); - if(fsaa) - { - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, config&2 ? 1 : 0); - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, config&2 ? fsaa : 0); - } - screen = SDL_SetVideoMode(scr_w, scr_h, hasbpp ? colorbits : 0, SDL_OPENGL|resize|fs); - if(screen) break; - } - if(!screen) fatal("Unable to create OpenGL screen"); - else - { - if(!hasbpp) conoutf("%d bit color buffer not supported - disabling", colorbits); - if(depthbits && (config&1)==0) conoutf("%d bit z-buffer not supported - disabling", depthbits); - if(fsaa && (config&2)==0) conoutf("%dx anti-aliasing not supported - disabling", fsaa); - } - - scr_w = screen->w; - scr_h = screen->h; - - fullscreen = fs!=0; - VIRTW = scr_w*VIRTH/scr_h; + int usedcolorbits = 0, useddepthbits = 0, usedfsaa = 0; + setupscreen(usedcolorbits, useddepthbits, usedfsaa); initlog("video: misc"); SDL_WM_SetCaption("AssaultCube", NULL); - #ifndef WIN32 - if(fs) - #endif - SDL_WM_GrabInput(SDL_GRAB_ON); keyrepeat(false); SDL_ShowCursor(0); initlog("gl"); - gl_init(scr_w, scr_h, hasbpp ? colorbits : 0, config&1 ? depthbits : 0, config&2 ? fsaa : 0); + gl_init(scr_w, scr_h, usedcolorbits, useddepthbits, usedfsaa); notexture = textureload("packages/misc/notexture.png"); if(!notexture) fatal("could not find core textures (hint: run AssaultCube from the parent of the bin directory)"); diff --git a/source/src/model.h b/source/src/model.h index f11b8300..df1b1cfb 100644 --- a/source/src/model.h +++ b/source/src/model.h @@ -39,6 +39,8 @@ struct model virtual char *name() = 0; virtual int type() = 0; + virtual void cleanup() = 0; + virtual void render(int anim, int varseed, float speed, int basetime, const vec &o, float yaw, float pitch, dynent *d, model *vwepmdl = NULL, float scale = 1.0f) = 0; virtual void setskin(int tex = 0) = 0; diff --git a/source/src/protos.h b/source/src/protos.h index 26eefacd..7c0cbf62 100644 --- a/source/src/protos.h +++ b/source/src/protos.h @@ -174,7 +174,7 @@ extern void renderaboveheadicon(playerent *p); struct Texture { char *name; - int xs, ys, bpp; + int xs, ys, bpp, clamp; GLuint id; }; extern Texture *notexture; @@ -183,6 +183,9 @@ extern void createtexture(int tnum, int w, int h, void *pixels, int clamp, bool extern Texture *textureload(const char *name, int clamp = 0); extern Texture *lookuptexture(int tex); extern void draw_envbox(int fogdist); +extern bool reloadtexture(Texture &t); +extern bool reloadtexture(const char *name); +extern void reloadtextures(); extern int maxtmus; extern void inittmus(); diff --git a/source/src/rendergl.cpp b/source/src/rendergl.cpp index 26f59033..b2bf904e 100644 --- a/source/src/rendergl.cpp +++ b/source/src/rendergl.cpp @@ -78,10 +78,6 @@ void gl_init(int w, int h, int bpp, int depth, int fsaa) camera1 = player1; } -void cleangl() -{ -} - void line(int x1, int y1, float z1, int x2, int y2, float z2) { glBegin(GL_POLYGON); @@ -528,7 +524,7 @@ void drawminimap(int w, int h) int size = 1< sizelimit) size /= 2; - if(size!=minimaplastsize) + if(size!=minimaplastsize && minimaptex) { glDeleteTextures(1, &minimaptex); minimaptex = 0; @@ -597,6 +593,17 @@ void drawminimap(int w, int h) glClearDepth(1.0); } +void cleanupgl() +{ + if(reflecttex) glDeleteTextures(1, &reflecttex); + if(refracttex) glDeleteTextures(1, &refracttex); + if(minimaptex) glDeleteTextures(1, &minimaptex); + reflecttex = refracttex = minimaptex = 0; + minimapdirty = true; + + if(glIsEnabled(GL_MULTISAMPLE)) glDisable(GL_MULTISAMPLE); +} + int xtraverts; VARP(hudgun, 0, 1, 1); diff --git a/source/src/rendermodel.cpp b/source/src/rendermodel.cpp index ccbec63a..0bdff895 100644 --- a/source/src/rendermodel.cpp +++ b/source/src/rendermodel.cpp @@ -102,6 +102,11 @@ model *loadmodel(const char *name, int i) return m; } +void cleanupmodels() +{ + enumerate(mdllookup, model *, m, m->cleanup()); +} + VARP(dynshadow, 0, 40, 100); struct batchedmodel diff --git a/source/src/renderparticles.cpp b/source/src/renderparticles.cpp index a8296843..13223866 100644 --- a/source/src/renderparticles.cpp +++ b/source/src/renderparticles.cpp @@ -204,6 +204,11 @@ void particleinit() parttex[5] = textureload("packages/misc/scorch.png"); } +void cleanupparticles() +{ + loopi(2) if(expmodtex[i]) { glDeleteTextures(1, &expmodtex[i]); expmodtex[i] = 0; } +} + void particlereset() { loopi(MAXPARTYPES) diff --git a/source/src/rendertext.cpp b/source/src/rendertext.cpp index b8a712c3..e013553c 100644 --- a/source/src/rendertext.cpp +++ b/source/src/rendertext.cpp @@ -234,3 +234,10 @@ void draw_text(const char *str, int left, int top) glEnd(); } +void reloadfonts() +{ + enumerate(fonts, font, f, + if(!reloadtexture(*f.tex)) fatal("failed to reload font texture"); + ); +} + diff --git a/source/src/texture.cpp b/source/src/texture.cpp index a17b9963..d69d8beb 100644 --- a/source/src/texture.cpp +++ b/source/src/texture.cpp @@ -130,6 +130,7 @@ Texture *textureload(const char *name, int clamp) t->xs = xs; t->ys = ys; t->bpp = bpp; + t->clamp = clamp; t->id = id; return t; } @@ -174,6 +175,36 @@ Texture *lookuptexture(int tex) return t; } +void cleanuptextures() +{ + enumerate(textures, Texture, t, + if(t.id) { glDeleteTextures(1, &t.id); t.id = 0; } + ); +} + +bool reloadtexture(Texture &t) +{ + if(t.id) return true; + int xs = 1, ys = 1, bpp = 0; + t.id = loadsurface(t.name, xs, ys, bpp, t.clamp); + t.xs = xs; + t.ys = ys; + t.bpp = bpp; + return t.id!=0; +} + +bool reloadtexture(const char *name) +{ + Texture *t = textures.access(path(name, true)); + if(t) return reloadtexture(*t); + return false; +} + +void reloadtextures() +{ + enumerate(textures, Texture, t, reloadtexture(t)); +} + Texture *sky[6] = {NULL, NULL, NULL, NULL, NULL, NULL}; void loadsky(char *basename) @@ -273,7 +304,9 @@ struct tmu { GL_MODULATE, { GL_TEXTURE, GL_PREVIOUS_ARB, GL_CONSTANT_ARB }, { GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA }, 1 } \ } -tmu tmus[4] = +#define MAXTMUS 4 + +tmu tmus[MAXTMUS] = { INVALIDTMU, INVALIDTMU, @@ -377,7 +410,7 @@ void inittmus() else if(hasTE && hasMT) { glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &val); - maxtmus = max(1, min(4, int(val))); + maxtmus = max(1, min(MAXTMUS, int(val))); loopi(maxtmus) { glActiveTexture_(GL_TEXTURE0_ARB+i); @@ -387,3 +420,9 @@ void inittmus() } } +void cleanuptmus() +{ + tmu invalidtmu = INVALIDTMU; + loopi(MAXTMUS) tmus[i] = invalidtmu; +} + diff --git a/source/src/vertmodel.h b/source/src/vertmodel.h index 0bf3ac73..025974df 100644 --- a/source/src/vertmodel.h +++ b/source/src/vertmodel.h @@ -121,6 +121,15 @@ struct vertmodel : model #undef ip_v_ai } + void cleanup() + { + if(statlist) + { + glDeleteLists(1, statlist); + statlist = 0; + } + } + void render(animstate &as, anpos &cur, anpos *prev, float ai_t) { if(!dynbuf) return; @@ -214,6 +223,16 @@ struct vertmodel : model DELETEA(shadows); } + void cleanup() + { + loopv(meshes) meshes[i]->cleanup(); + if(shadows) + { + glDeleteTextures(numframes, shadows); + DELETEA(shadows); + } + } + bool link(part *link, const char *tag) { loopi(numtags) if(!strcmp(tags[i].name, tag)) @@ -568,6 +587,11 @@ struct vertmodel : model char *name() { return loadname; } + void cleanup() + { + loopv(parts) parts[i]->cleanup(); + } + bool link(part *link, const char *tag) { loopv(parts) if(parts[i]->link(link, tag)) return true;