X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=cl_screen.c;h=55603fe6c6a9df733d18619dfe32a360ff44275c;hb=2c2dca086977f62083109084dc8c600241ace9f2;hp=7f53840b751c51e2dad92edf988b9758d3cc8bfa;hpb=2d6bad9761b2841d7cf6c7bbb96b0dfcf8923167;p=xonotic%2Fdarkplaces.git diff --git a/cl_screen.c b/cl_screen.c index 7f53840b..55603fe6 100644 --- a/cl_screen.c +++ b/cl_screen.c @@ -50,6 +50,7 @@ cvar_t scr_stipple = {0, "scr_stipple", "0", "interlacing-like stippling of the cvar_t scr_refresh = {0, "scr_refresh", "1", "allows you to completely shut off rendering for benchmarking purposes"}; cvar_t shownetgraph = {CVAR_SAVE, "shownetgraph", "0", "shows a graph of packet sizes and other information, 0 = off, 1 = show client netgraph, 2 = show client and server netgraphs (when hosting a server)"}; +#define AVI_MASTER_INDEX_SIZE 640 // GB ought to be enough for anyone int jpeg_supported = false; @@ -112,10 +113,9 @@ void SCR_DrawCenterString (void) int remaining; int color; - if(gamemode == GAME_NEXUIZ) - if(cl.intermission == 2) // in Nexuiz finale (voting screen), - if(sb_showscores) // make TAB hide vote messages - return; + if(cl.intermission == 2) // in finale, + if(sb_showscores) // make TAB hide the finale message (sb_showscores overrides finale in sbar.c) + return; // the finale prints the characters one at a time, except if printspeed is an absurdly high value if (cl.intermission && scr_printspeed.value > 0 && scr_printspeed.value < 1000000) @@ -601,7 +601,6 @@ void SCR_BeginLoadingPlaque (void) Log_Start(); Host_StartVideo(); - S_StopAllSounds(); SCR_UpdateLoadingScreen(false); } @@ -684,7 +683,8 @@ void R_TimeReport_Frame(void) if (loc) sprintf(r_speeds_string + strlen(r_speeds_string), "Location: %s\n", loc->name); sprintf(r_speeds_string + strlen(r_speeds_string), "org:'%+8.2f %+8.2f %+8.2f' dir:'%+2.3f %+2.3f %+2.3f'\n", r_view.origin[0], r_view.origin[1], r_view.origin[2], r_view.forward[0], r_view.forward[1], r_view.forward[2]); - sprintf(r_speeds_string + strlen(r_speeds_string), "%5i entities%6i surfaces%6i triangles%5i leafs%5i portals%6i particles\n", r_refdef.stats.entities, r_refdef.stats.entities_surfaces, r_refdef.stats.entities_triangles, r_refdef.stats.world_leafs, r_refdef.stats.world_portals, r_refdef.stats.particles); + sprintf(r_speeds_string + strlen(r_speeds_string), "%7i surfaces%7i triangles %5i entities (%7i surfaces%7i triangles)\n", r_refdef.stats.world_surfaces, r_refdef.stats.world_triangles, r_refdef.stats.entities, r_refdef.stats.entities_surfaces, r_refdef.stats.entities_triangles); + sprintf(r_speeds_string + strlen(r_speeds_string), "%5ileafs%5i portals%6i particles%6i decals\n", r_refdef.stats.world_leafs, r_refdef.stats.world_portals, r_refdef.stats.particles, r_refdef.stats.decals); sprintf(r_speeds_string + strlen(r_speeds_string), "%4i lights%4i clears%4i scissored%7i light%7i shadow%7i dynamic\n", r_refdef.stats.lights, r_refdef.stats.lights_clears, r_refdef.stats.lights_scissored, r_refdef.stats.lights_lighttriangles, r_refdef.stats.lights_shadowtriangles, r_refdef.stats.lights_dynamicshadowtriangles); if (r_refdef.stats.bloom) sprintf(r_speeds_string + strlen(r_speeds_string), "rendered%6i meshes%8i triangles bloompixels%8i copied%8i drawn\n", r_refdef.stats.meshes, r_refdef.stats.meshes_elements / 3, r_refdef.stats.bloom_copypixels, r_refdef.stats.bloom_drawpixels); @@ -922,34 +922,100 @@ static void SCR_CaptureVideo_RIFF_Pop(void) } } -static void SCR_CaptureVideo_RIFF_IndexEntry(const char *chunkfourcc, int chunksize, int flags) +static void GrowBuf(sizebuf_t *buf, int extralen) { - if (cls.capturevideo.riffstacklevel != 2) - Sys_Error("SCR_Capturevideo_RIFF_IndexEntry: RIFF stack level is %i (should be 2)\n", cls.capturevideo.riffstacklevel); - if (cls.capturevideo.riffindexbuffer.cursize + 16 > cls.capturevideo.riffindexbuffer.maxsize) + if(buf->cursize + extralen > buf->maxsize) { - int oldsize = cls.capturevideo.riffindexbuffer.maxsize; + int oldsize = buf->maxsize; unsigned char *olddata; - olddata = cls.capturevideo.riffindexbuffer.data; - cls.capturevideo.riffindexbuffer.maxsize = max(cls.capturevideo.riffindexbuffer.maxsize * 2, 4096); - cls.capturevideo.riffindexbuffer.data = Mem_Alloc(tempmempool, cls.capturevideo.riffindexbuffer.maxsize); - if (olddata) + olddata = buf->data; + buf->maxsize = max(buf->maxsize * 2, 4096); + buf->data = Mem_Alloc(tempmempool, buf->maxsize); + if(olddata) { - memcpy(cls.capturevideo.riffindexbuffer.data, olddata, oldsize); + memcpy(buf->data, olddata, oldsize); Mem_Free(olddata); } } +} + +static void SCR_CaptureVideo_RIFF_IndexEntry(const char *chunkfourcc, int chunksize, int flags) +{ + if (cls.capturevideo.riffstacklevel != 2) + Sys_Error("SCR_Capturevideo_RIFF_IndexEntry: RIFF stack level is %i (should be 2)\n", cls.capturevideo.riffstacklevel); + GrowBuf(&cls.capturevideo.riffindexbuffer, 16); + SCR_CaptureVideo_RIFF_Flush(); MSG_WriteUnterminatedString(&cls.capturevideo.riffindexbuffer, chunkfourcc); MSG_WriteLong(&cls.capturevideo.riffindexbuffer, flags); MSG_WriteLong(&cls.capturevideo.riffindexbuffer, (int)FS_Tell(cls.capturevideo.videofile) - cls.capturevideo.riffstackstartoffset[1]); MSG_WriteLong(&cls.capturevideo.riffindexbuffer, chunksize); } +static void SCR_CaptureVideo_RIFF_MakeIxChunk(const char *fcc, const char *dwChunkId, fs_offset_t masteridx_counter, int *masteridx_count, fs_offset_t masteridx_start) +{ + int nMatching; + int i; + fs_offset_t ix = SCR_CaptureVideo_RIFF_GetPosition(); + fs_offset_t pos; + + if(*masteridx_count >= AVI_MASTER_INDEX_SIZE) + return; + + nMatching = 0; // go through index and enumerate them + for(i = 0; i < cls.capturevideo.riffindexbuffer.cursize; i += 16) + if(!memcmp(cls.capturevideo.riffindexbuffer.data + i, dwChunkId, 4)) + ++nMatching; + + SCR_CaptureVideo_RIFF_Push(fcc, NULL); + SCR_CaptureVideo_RIFF_Write16(2); // wLongsPerEntry + SCR_CaptureVideo_RIFF_Write16(0x0100); // bIndexType=1, bIndexSubType=0 + SCR_CaptureVideo_RIFF_Write32(nMatching); // nEntriesInUse + SCR_CaptureVideo_RIFF_WriteFourCC(dwChunkId); // dwChunkId + SCR_CaptureVideo_RIFF_Write32(cls.capturevideo.videofile_ix_movistart & (fs_offset_t) 0xFFFFFFFFu); + SCR_CaptureVideo_RIFF_Write32(((fs_offset_t) cls.capturevideo.videofile_ix_movistart) >> 32); + SCR_CaptureVideo_RIFF_Write32(0); // dwReserved + + for(i = 0; i < cls.capturevideo.riffindexbuffer.cursize; i += 16) + if(!memcmp(cls.capturevideo.riffindexbuffer.data + i, dwChunkId, 4)) + { + unsigned int *p = (unsigned int *) (cls.capturevideo.riffindexbuffer.data + i); + unsigned int flags = p[1]; + unsigned int rpos = p[2]; + unsigned int size = p[3]; + size &= ~0x80000000; + if(!(flags & 0x10)) // no keyframe? + size |= 0x80000000; + SCR_CaptureVideo_RIFF_Write32(rpos + 8); + SCR_CaptureVideo_RIFF_Write32(size); + } + + SCR_CaptureVideo_RIFF_Pop(); + pos = SCR_CaptureVideo_RIFF_GetPosition(); + SCR_CaptureVideo_RIFF_Flush(); + + FS_Seek(cls.capturevideo.videofile, masteridx_start + 16 * *masteridx_count, SEEK_SET); + SCR_CaptureVideo_RIFF_Write32(ix & (fs_offset_t) 0xFFFFFFFFu); + SCR_CaptureVideo_RIFF_Write32(((fs_offset_t) ix) >> 32); + SCR_CaptureVideo_RIFF_Write32(pos - ix); + SCR_CaptureVideo_RIFF_Write32(nMatching); + SCR_CaptureVideo_RIFF_Flush(); + + FS_Seek(cls.capturevideo.videofile, masteridx_counter, SEEK_SET); + SCR_CaptureVideo_RIFF_Write32(++*masteridx_count); + SCR_CaptureVideo_RIFF_Flush(); + + FS_Seek(cls.capturevideo.videofile, 0, SEEK_END); +} + static void SCR_CaptureVideo_RIFF_Finish(qboolean final) { // close the "movi" list SCR_CaptureVideo_RIFF_Pop(); - // write the idx1 chunk that we've been building while saving the frames + if(cls.capturevideo.videofile_ix_master_video_inuse_offset) + SCR_CaptureVideo_RIFF_MakeIxChunk("ix00", "00dc", cls.capturevideo.videofile_ix_master_video_inuse_offset, &cls.capturevideo.videofile_ix_master_video_inuse, cls.capturevideo.videofile_ix_master_video_start_offset); + if(cls.capturevideo.videofile_ix_master_audio_inuse_offset) + SCR_CaptureVideo_RIFF_MakeIxChunk("ix01", "01wb", cls.capturevideo.videofile_ix_master_audio_inuse_offset, &cls.capturevideo.videofile_ix_master_audio_inuse, cls.capturevideo.videofile_ix_master_audio_start_offset); + // write the idx1 chunk that we've been building while saving the frames (for old style players) if(final && cls.capturevideo.videofile_firstchunkframes_offset) // TODO replace index creating by OpenDML ix##/##ix/indx chunk so it works for more than one AVI part too { @@ -987,12 +1053,13 @@ static void SCR_CaptureVideo_RIFF_OverflowCheck(int framesize) // if this would overflow the windows limit of 1GB per RIFF chunk, we need // to close the current RIFF chunk and open another for future frames - if (8 + cursize + framesize + cls.capturevideo.riffindexbuffer.cursize + 8 > 1<<30) + if (8 + cursize + framesize + cls.capturevideo.riffindexbuffer.cursize + 8 + cls.capturevideo.riffindexbuffer.cursize + 64 > 1<<30) // note that the Ix buffer takes less space... I just don't dare to / 2 here now... sorry, maybe later { SCR_CaptureVideo_RIFF_Finish(false); // begin a new 1GB extended section of the AVI SCR_CaptureVideo_RIFF_Push("RIFF", "AVIX"); SCR_CaptureVideo_RIFF_Push("LIST", "movi"); + cls.capturevideo.videofile_ix_movistart = cls.capturevideo.riffstackstartoffset[1]; } } @@ -1169,11 +1236,25 @@ Cr = R * .500 + G * -.419 + B * -.0813 + 128.; SCR_CaptureVideo_RIFF_Write32(0); // color used SCR_CaptureVideo_RIFF_Write32(0); // color important SCR_CaptureVideo_RIFF_Pop(); + // master index + SCR_CaptureVideo_RIFF_Push("indx", NULL); + SCR_CaptureVideo_RIFF_Write16(4); // wLongsPerEntry + SCR_CaptureVideo_RIFF_Write16(0); // bIndexSubType=0, bIndexType=0 + cls.capturevideo.videofile_ix_master_video_inuse_offset = SCR_CaptureVideo_RIFF_GetPosition(); + SCR_CaptureVideo_RIFF_Write32(0); // nEntriesInUse + SCR_CaptureVideo_RIFF_WriteFourCC("00dc"); // dwChunkId + SCR_CaptureVideo_RIFF_Write32(0); // dwReserved1 + SCR_CaptureVideo_RIFF_Write32(0); // dwReserved2 + SCR_CaptureVideo_RIFF_Write32(0); // dwReserved3 + cls.capturevideo.videofile_ix_master_video_start_offset = SCR_CaptureVideo_RIFF_GetPosition(); + for(i = 0; i < AVI_MASTER_INDEX_SIZE * 4; ++i) + SCR_CaptureVideo_RIFF_Write32(0); // fill up later + SCR_CaptureVideo_RIFF_Pop(); // extended format (aspect!) SCR_CaptureVideo_RIFF_Push("vprp", NULL); SCR_CaptureVideo_RIFF_Write32(0); // VideoFormatToken SCR_CaptureVideo_RIFF_Write32(0); // VideoStandard - SCR_CaptureVideo_RIFF_Write32(cls.capturevideo.framerate); // dwVerticalRefreshRate (bogus) + SCR_CaptureVideo_RIFF_Write32((int)cls.capturevideo.framerate); // dwVerticalRefreshRate (bogus) SCR_CaptureVideo_RIFF_Write32(width); // dwHTotalInT SCR_CaptureVideo_RIFF_Write32(height); // dwVTotalInLines FindFraction(aspect, &n, &d, 1000); @@ -1224,9 +1305,25 @@ Cr = R * .500 + G * -.419 + B * -.0813 + 128.; SCR_CaptureVideo_RIFF_Write16(16); // bits per sample SCR_CaptureVideo_RIFF_Write16(0); // size SCR_CaptureVideo_RIFF_Pop(); + // master index + SCR_CaptureVideo_RIFF_Push("indx", NULL); + SCR_CaptureVideo_RIFF_Write16(4); // wLongsPerEntry + SCR_CaptureVideo_RIFF_Write16(0); // bIndexSubType=0, bIndexType=0 + cls.capturevideo.videofile_ix_master_audio_inuse_offset = SCR_CaptureVideo_RIFF_GetPosition(); + SCR_CaptureVideo_RIFF_Write32(0); // nEntriesInUse + SCR_CaptureVideo_RIFF_WriteFourCC("01wb"); // dwChunkId + SCR_CaptureVideo_RIFF_Write32(0); // dwReserved1 + SCR_CaptureVideo_RIFF_Write32(0); // dwReserved2 + SCR_CaptureVideo_RIFF_Write32(0); // dwReserved3 + cls.capturevideo.videofile_ix_master_audio_start_offset = SCR_CaptureVideo_RIFF_GetPosition(); + for(i = 0; i < AVI_MASTER_INDEX_SIZE * 4; ++i) + SCR_CaptureVideo_RIFF_Write32(0); // fill up later + SCR_CaptureVideo_RIFF_Pop(); SCR_CaptureVideo_RIFF_Pop(); } + cls.capturevideo.videofile_ix_master_audio_inuse = cls.capturevideo.videofile_ix_master_video_inuse = 0; + // extended header (for total #frames) SCR_CaptureVideo_RIFF_Push("LIST", "odml"); SCR_CaptureVideo_RIFF_Push("dmlh", NULL); @@ -1258,6 +1355,7 @@ Cr = R * .500 + G * -.419 + B * -.0813 + 128.; SCR_CaptureVideo_RIFF_Pop(); // begin the actual video section now SCR_CaptureVideo_RIFF_Push("LIST", "movi"); + cls.capturevideo.videofile_ix_movistart = cls.capturevideo.riffstackstartoffset[1]; // we're done with the headers now... SCR_CaptureVideo_RIFF_Flush(); if (cls.capturevideo.riffstacklevel != 2) @@ -1581,6 +1679,7 @@ static void R_Envmap_f (void) r_view.width = size; r_view.height = size; r_view.depth = 1; + r_view.useperspective = true; r_view.frustum_x = tan(90 * M_PI / 360.0); r_view.frustum_y = tan(90 * M_PI / 360.0); @@ -1609,36 +1708,22 @@ static void R_Envmap_f (void) //============================================================================= -// LordHavoc: SHOWLMP stuff -#define SHOWLMP_MAXLABELS 256 -typedef struct showlmp_s -{ - qboolean isactive; - float x; - float y; - char label[32]; - char pic[128]; -} -showlmp_t; - -showlmp_t showlmp[SHOWLMP_MAXLABELS]; - void SHOWLMP_decodehide(void) { int i; char *lmplabel; lmplabel = MSG_ReadString(); - for (i = 0;i < SHOWLMP_MAXLABELS;i++) - if (showlmp[i].isactive && strcmp(showlmp[i].label, lmplabel) == 0) + for (i = 0;i < cl.num_showlmps;i++) + if (cl.showlmps[i].isactive && strcmp(cl.showlmps[i].label, lmplabel) == 0) { - showlmp[i].isactive = false; + cl.showlmps[i].isactive = false; return; } } void SHOWLMP_decodeshow(void) { - int i, k; + int k; char lmplabel[256], picname[256]; float x, y; strlcpy (lmplabel,MSG_ReadString(), sizeof (lmplabel)); @@ -1653,41 +1738,37 @@ void SHOWLMP_decodeshow(void) x = MSG_ReadShort(); y = MSG_ReadShort(); } - k = -1; - for (i = 0;i < SHOWLMP_MAXLABELS;i++) - if (showlmp[i].isactive) - { - if (strcmp(showlmp[i].label, lmplabel) == 0) - { - k = i; - break; // drop out to replace it - } - } - else if (k < 0) // find first empty one to replace - k = i; - if (k < 0) - return; // none found to replace - // change existing one - showlmp[k].isactive = true; - strlcpy (showlmp[k].label, lmplabel, sizeof (showlmp[k].label)); - strlcpy (showlmp[k].pic, picname, sizeof (showlmp[k].pic)); - showlmp[k].x = x; - showlmp[k].y = y; + if (!cl.showlmps || cl.num_showlmps >= cl.max_showlmps) + { + showlmp_t *oldshowlmps = cl.showlmps; + cl.max_showlmps += 16; + cl.showlmps = Mem_Alloc(cls.levelmempool, cl.max_showlmps * sizeof(showlmp_t)); + if (cl.num_showlmps) + memcpy(cl.showlmps, oldshowlmps, cl.num_showlmps * sizeof(showlmp_t)); + if (oldshowlmps) + Mem_Free(oldshowlmps); + } + for (k = 0;k < cl.max_showlmps;k++) + if (cl.showlmps[k].isactive && !strcmp(cl.showlmps[k].label, lmplabel)) + break; + if (k == cl.max_showlmps) + for (k = 0;k < cl.max_showlmps;k++) + if (!cl.showlmps[k].isactive) + break; + cl.showlmps[k].isactive = true; + strlcpy (cl.showlmps[k].label, lmplabel, sizeof (cl.showlmps[k].label)); + strlcpy (cl.showlmps[k].pic, picname, sizeof (cl.showlmps[k].pic)); + cl.showlmps[k].x = x; + cl.showlmps[k].y = y; + cl.num_showlmps = max(cl.num_showlmps, k + 1); } void SHOWLMP_drawall(void) { int i; - for (i = 0;i < SHOWLMP_MAXLABELS;i++) - if (showlmp[i].isactive) - DrawQ_Pic(showlmp[i].x, showlmp[i].y, Draw_CachePic(showlmp[i].pic, true), 0, 0, 1, 1, 1, 1, 0); -} - -void SHOWLMP_clear(void) -{ - int i; - for (i = 0;i < SHOWLMP_MAXLABELS;i++) - showlmp[i].isactive = false; + for (i = 0;i < cl.num_showlmps;i++) + if (cl.showlmps[i].isactive) + DrawQ_Pic(cl.showlmps[i].x, cl.showlmps[i].y, Draw_CachePic(cl.showlmps[i].pic, true), 0, 0, 1, 1, 1, 1, 0); } /* @@ -1777,10 +1858,14 @@ void SCR_DrawScreen (void) R_Mesh_Start(); if (r_timereport_active) - R_TimeReport("setup"); + R_TimeReport("screensetup"); R_UpdateVariables(); + // Quake uses clockwise winding, so these are swapped + r_view.cullface_front = GL_BACK; + r_view.cullface_back = GL_FRONT; + if (cls.signon == SIGNONS) { float size; @@ -1815,6 +1900,7 @@ void SCR_DrawScreen (void) // this it simply assumes the requested fov is the vertical fov // for a 4x3 display, if the ratio is not 4x3 this makes the fov // higher/lower according to the ratio + r_view.useperspective = true; r_view.frustum_y = tan(scr_fov.value * M_PI / 360.0) * (3.0/4.0) * cl.viewzoom; r_view.frustum_x = r_view.frustum_y * (float)r_view.width / (float)r_view.height / vid_pixelheight.value; @@ -1835,6 +1921,7 @@ void SCR_DrawScreen (void) r_view.y = 0; r_view.z = 0; + r_view.useperspective = true; r_view.frustum_y = tan(scr_zoomwindow_fov.value * M_PI / 360.0) * (3.0/4.0) * cl.viewzoom; r_view.frustum_x = r_view.frustum_y * vid_pixelheight.value * (float)r_view.width / (float)r_view.height; @@ -1854,6 +1941,7 @@ void SCR_DrawScreen (void) r_view.x = 0; r_view.y = 0; r_view.z = 0; + r_view.useperspective = false; } // draw 2D stuff @@ -1928,6 +2016,7 @@ void SCR_UpdateLoadingScreen (qboolean clear) GL_Color(1,1,1,1); GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GL_DepthRange(0, 1); + GL_PolygonOffset(0, 0); GL_DepthTest(false); R_Mesh_VertexPointer(vertex3f, 0, 0); R_Mesh_ColorPointer(NULL, 0, 0); @@ -2033,7 +2122,8 @@ void CL_UpdateScreen(void) qglDepthMask(1);CHECKGLERROR qglColorMask(1,1,1,1);CHECKGLERROR qglClearColor(0,0,0,0);CHECKGLERROR - qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR + R_ClearScreen(); + r_view.clear = false; if(scr_stipple.integer) { @@ -2058,7 +2148,7 @@ void CL_UpdateScreen(void) qglDisable(GL_POLYGON_STIPPLE); if (r_timereport_active) - R_TimeReport("clear"); + R_TimeReport("screenclear"); qglDrawBuffer(GL_BACK); @@ -2116,5 +2206,4 @@ void CL_UpdateScreen(void) void CL_Screen_NewMap(void) { - SHOWLMP_clear(); }