void R_MME_Init(void) { // MME cvars mme_blurFrames = ri.Cvar_Get ( "mme_blurFrames", "0", CVAR_ARCHIVE ); mme_blurOverlap = ri.Cvar_Get ("mme_blurOverlap", "0", CVAR_ARCHIVE ); mme_blurType = ri.Cvar_Get ( "mme_blurType", "gaussian", CVAR_ARCHIVE ); mme_blurJitter = ri.Cvar_Get ( "mme_blurJitter", "1", CVAR_ARCHIVE ); mme_blurStrength = ri.Cvar_Get ( "mme_blurStrength", "0", CVAR_ARCHIVE ); mme_dofFrames = ri.Cvar_Get ( "mme_dofFrames", "0", CVAR_ARCHIVE ); mme_dofRadius = ri.Cvar_Get ( "mme_dofRadius", "2", CVAR_ARCHIVE ); mme_dofVisualize = ri.Cvar_Get ( "mme_dofVisualize", "0", CVAR_TEMP ); mme_cpuSSE2 = ri.Cvar_Get ( "mme_cpuSSE2", "0", CVAR_ARCHIVE ); mme_depthRange = ri.Cvar_Get ( "mme_depthRange", "2000", CVAR_ARCHIVE ); mme_depthFocus = ri.Cvar_Get ( "mme_depthFocus", "0", CVAR_ARCHIVE ); //mme_saveStencil = ri.Cvar_Get ( "mme_saveStencil", "0", CVAR_ARCHIVE ); mme_saveDepth = ri.Cvar_Get ( "mme_saveDepth", "0", CVAR_ARCHIVE ); Com_Memset(&shotDataMain, 0, sizeof(shotDataMain)); Com_Memset(&shotDataLeft, 0, sizeof(shotDataLeft)); R_MME_CheckCvars(qtrue, &shotDataMain); R_MME_InitMemory(qtrue, &shotDataMain); R_MME_CheckCvars(qtrue, &shotDataLeft); R_MME_InitMemory(qtrue, &shotDataLeft); // avoid crash if mme_dofVisualize set when renderer starts if (mme_dofVisualize->integer) { shotDataMain.forceReset = qtrue; } #if 0 //FIXME testing shotDataMain.dofFocus = 1024; shotDataMain.dofRadius = 5; //FIXME testing shotDataLeft.dofFocus = 1024; shotDataLeft.dofRadius = 5; #endif }
qboolean R_MME_TakeShot( void ) { int pixelCount; byte inSound[MME_SAMPLERATE] = {0}; int sizeSound = 0; qboolean audio = qfalse, audioTaken = qfalse; qboolean doGamma; mmeBlurControl_t* blurControl = &blurData.control; if ( !shotData.take || allocFailed || tr.finishStereo ) return qfalse; shotData.take = qfalse; pixelCount = glConfig.vidHeight * glConfig.vidWidth; doGamma = (qboolean)(( mme_screenShotGamma->integer || (tr.overbrightBits > 0) ) && (glConfig.deviceSupportsGamma )); R_MME_CheckCvars(); //Special early version using the framebuffer if ( mme_saveShot->integer && blurControl->totalFrames > 0 && R_FrameBuffer_Blur( blurControl->Float[ blurControl->totalIndex ], blurControl->totalIndex, blurControl->totalFrames ) ) { byte *shotBuf; float fps; if ( ++(blurControl->totalIndex) < blurControl->totalFrames ) return qtrue; blurControl->totalIndex = 0; shotBuf = (byte *)ri.Hunk_AllocateTempMemory( pixelCount * 3 ); R_MME_MultiShot( shotBuf ); if ( doGamma ) R_GammaCorrect( shotBuf, pixelCount * 3 ); fps = shotData.fps / ( blurControl->totalFrames ); audio = ri.S_MMEAviImport(inSound, &sizeSound); R_MME_SaveShot( &shotData.main, glConfig.vidWidth, glConfig.vidHeight, fps, shotBuf, audio, sizeSound, inSound ); ri.Hunk_FreeTempMemory( shotBuf ); return qtrue; } /* Test if we need to do blurred shots */ if ( blurControl->totalFrames > 0 ) { mmeBlurBlock_t *blurShot = &blurData.shot; mmeBlurBlock_t *blurDepth = &blurData.depth; // mmeBlurBlock_t *blurStencil = &blurData.stencil; /* Test if we blur with overlapping frames */ if ( blurControl->overlapFrames ) { /* First frame in a sequence, fill the buffer with the last frames */ if (blurControl->totalIndex == 0) { int i; for ( i = 0; i < blurControl->overlapFrames; i++ ) { if ( mme_saveShot->integer ) { R_MME_BlurOverlapAdd( blurShot, i ); } if ( mme_saveDepth->integer ) { R_MME_BlurOverlapAdd( blurDepth, i ); } // if ( mme_saveStencil->integer ) { // R_MME_BlurOverlapAdd( blurStencil, i ); // } blurControl->totalIndex++; } } if ( mme_saveShot->integer == 1 ) { byte* shotBuf = R_MME_BlurOverlapBuf( blurShot ); R_MME_MultiShot( shotBuf ); if ( doGamma && mme_blurGamma->integer ) { R_GammaCorrect( shotBuf, glConfig.vidWidth * glConfig.vidHeight * 3 ); } R_MME_BlurOverlapAdd( blurShot, 0 ); } if ( mme_saveDepth->integer == 1 ) { R_MME_GetDepth( R_MME_BlurOverlapBuf( blurDepth ) ); R_MME_BlurOverlapAdd( blurDepth, 0 ); } // if ( mme_saveStencil->integer == 1 ) { // R_MME_GetStencil( R_MME_BlurOverlapBuf( blurStencil ) ); // R_MME_BlurOverlapAdd( blurStencil, 0 ); // } blurControl->overlapIndex++; blurControl->totalIndex++; } else { byte *outAlloc; __m64 *outAlign; outAlloc = (byte *)ri.Hunk_AllocateTempMemory( pixelCount * 3 + 16); outAlign = (__m64 *)((((intptr_t)(outAlloc)) + 15) & ~15); if ( mme_saveShot->integer == 1 ) { R_MME_MultiShot( (byte*)outAlign ); if ( doGamma && mme_blurGamma->integer ) { R_GammaCorrect( (byte *) outAlign, pixelCount * 3 ); } R_MME_BlurAccumAdd( blurShot, outAlign ); } if ( mme_saveDepth->integer == 1 ) { R_MME_GetDepth( (byte *)outAlign ); R_MME_BlurAccumAdd( blurDepth, outAlign ); } // if ( mme_saveStencil->integer == 1 ) { // R_MME_GetStencil( (byte *)outAlign ); // R_MME_BlurAccumAdd( blurStencil, outAlign ); // } ri.Hunk_FreeTempMemory( outAlloc ); blurControl->totalIndex++; } if ( blurControl->totalIndex >= blurControl->totalFrames ) { float fps; blurControl->totalIndex = 0; fps = shotData.fps / ( blurControl->totalFrames ); if ( mme_saveShot->integer == 1 ) { R_MME_BlurAccumShift( blurShot ); if (doGamma && !mme_blurGamma->integer) R_GammaCorrect( (byte *)blurShot->accum, pixelCount * 3); } if ( mme_saveDepth->integer == 1 ) R_MME_BlurAccumShift( blurDepth ); // if ( mme_saveStencil->integer == 1 ) // R_MME_BlurAccumShift( blurStencil ); audio = ri.S_MMEAviImport(inSound, &sizeSound); audioTaken = qtrue; // Big test for an rgba shot if ( mme_saveShot->integer == 1 && shotData.main.type == mmeShotTypeRGBA ) { int i; byte *alphaShot = (byte *)ri.Hunk_AllocateTempMemory( pixelCount * 4); byte *rgbData = (byte *)(blurShot->accum ); if ( mme_saveDepth->integer == 1 ) { byte *depthData = (byte *)( blurDepth->accum ); for ( i = 0;i < pixelCount; i++ ) { alphaShot[i*4+0] = rgbData[i*3+0]; alphaShot[i*4+1] = rgbData[i*3+1]; alphaShot[i*4+2] = rgbData[i*3+2]; alphaShot[i*4+3] = depthData[i]; } /* } else if ( mme_saveStencil->integer == 1) { byte *stencilData = (byte *)( blurStencil->accum ); for ( i = 0;i < pixelCount; i++ ) { alphaShot[i*4+0] = rgbData[i*3+0]; alphaShot[i*4+1] = rgbData[i*3+1]; alphaShot[i*4+2] = rgbData[i*3+2]; alphaShot[i*4+3] = stencilData[i]; } */ } R_MME_SaveShot( &shotData.main, glConfig.vidWidth, glConfig.vidHeight, fps, alphaShot, audio, sizeSound, inSound ); ri.Hunk_FreeTempMemory( alphaShot ); } else { if ( mme_saveShot->integer == 1 ) R_MME_SaveShot( &shotData.main, glConfig.vidWidth, glConfig.vidHeight, fps, (byte *)( blurShot->accum ), audio, sizeSound, inSound ); if ( mme_saveDepth->integer == 1 ) R_MME_SaveShot( &shotData.depth, glConfig.vidWidth, glConfig.vidHeight, fps, (byte *)( blurDepth->accum ), audio, sizeSound, inSound ); // if ( mme_saveStencil->integer == 1 ) // R_MME_SaveShot( &shotData.stencil, glConfig.vidWidth, glConfig.vidHeight, fps, (byte *)( blurStencil->accum), audio, sizeSound, inSound ); } } } if ( mme_saveShot->integer > 1 || (!blurControl->totalFrames && mme_saveShot->integer )) { byte *shotBuf = (byte *)ri.Hunk_AllocateTempMemory( pixelCount * 5 ); R_MME_MultiShot( shotBuf ); if ( doGamma ) R_GammaCorrect( shotBuf, pixelCount * 3 ); if ( shotData.main.type == mmeShotTypeRGBA ) { int i; byte *alphaBuf = shotBuf + pixelCount * 4; if ( mme_saveDepth->integer > 1 || (!blurControl->totalFrames && mme_saveDepth->integer )) { R_MME_GetDepth( alphaBuf ); // } else if ( mme_saveStencil->integer > 1 || (!blurControl->totalFrames && mme_saveStencil->integer )) { // R_MME_GetStencil( alphaBuf ); } for ( i = pixelCount - 1 ; i >= 0; i-- ) { shotBuf[i * 4 + 0] = shotBuf[i*3 + 0]; shotBuf[i * 4 + 1] = shotBuf[i*3 + 1]; shotBuf[i * 4 + 2] = shotBuf[i*3 + 2]; shotBuf[i * 4 + 3] = alphaBuf[i]; } } if (!audioTaken) audio = ri.S_MMEAviImport(inSound, &sizeSound); audioTaken = qtrue; R_MME_SaveShot( &shotData.main, glConfig.vidWidth, glConfig.vidHeight, shotData.fps, shotBuf, audio, sizeSound, inSound ); ri.Hunk_FreeTempMemory( shotBuf ); } if ( shotData.main.type == mmeShotTypeRGB ) { /* if ( mme_saveStencil->integer > 1 || ( !blurControl->totalFrames && mme_saveStencil->integer) ) { byte *stencilShot = (byte *)ri.Hunk_AllocateTempMemory( pixelCount * 1); R_MME_GetStencil( stencilShot ); if (!audioTaken && ((mme_saveStencil->integer > 1 && mme_saveShot->integer > 1) || (mme_saveStencil->integer == 1 && mme_saveShot->integer == 1))) audio = ri.S_MMEAviImport(inSound, &sizeSound); R_MME_SaveShot( &shotData.stencil, glConfig.vidWidth, glConfig.vidHeight, shotData.fps, stencilShot, audio, sizeSound, inSound ); ri.Hunk_FreeTempMemory( stencilShot ); } */ if ( mme_saveDepth->integer > 1 || ( !blurControl->totalFrames && mme_saveDepth->integer) ) { byte *depthShot = (byte *)ri.Hunk_AllocateTempMemory( pixelCount * 1); R_MME_GetDepth( depthShot ); if (!audioTaken && ((mme_saveDepth->integer > 1 && mme_saveShot->integer > 1) || (mme_saveDepth->integer == 1 && mme_saveShot->integer == 1))) audio = ri.S_MMEAviImport(inSound, &sizeSound); R_MME_SaveShot( &shotData.depth, glConfig.vidWidth, glConfig.vidHeight, shotData.fps, depthShot, audio, sizeSound, inSound ); ri.Hunk_FreeTempMemory( depthShot ); } } return qtrue; }