From 1c85be8625b343c6301a0241d83beee33c1c470e Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Thu, 8 Sep 2011 15:39:03 +0200 Subject: [PATCH 1/3] Implement frame dumping in D3D11. Fixes issue 4831. --- Source/Core/VideoCommon/Src/RenderBase.cpp | 2 +- Source/Core/VideoCommon/Src/RenderBase.h | 2 +- .../Plugins/Plugin_VideoDX11/Src/Render.cpp | 115 ++++++++++++++++-- Source/Plugins/Plugin_VideoDX9/Src/Render.cpp | 28 +++-- Source/Plugins/Plugin_VideoOGL/Src/Render.cpp | 18 +-- 5 files changed, 133 insertions(+), 32 deletions(-) diff --git a/Source/Core/VideoCommon/Src/RenderBase.cpp b/Source/Core/VideoCommon/Src/RenderBase.cpp index d89e582860..06f4c81ab6 100644 --- a/Source/Core/VideoCommon/Src/RenderBase.cpp +++ b/Source/Core/VideoCommon/Src/RenderBase.cpp @@ -52,7 +52,7 @@ int OSDChoice, OSDTime; Renderer *g_renderer = NULL; -bool s_bLastFrameDumped = false; +bool bLastFrameDumped = false; std::mutex Renderer::s_criticalScreenshot; std::string Renderer::s_sScreenshotName; diff --git a/Source/Core/VideoCommon/Src/RenderBase.h b/Source/Core/VideoCommon/Src/RenderBase.h index b2c2c7ecfb..48f096851f 100644 --- a/Source/Core/VideoCommon/Src/RenderBase.h +++ b/Source/Core/VideoCommon/Src/RenderBase.h @@ -41,7 +41,7 @@ extern int frameCount; extern int OSDChoice, OSDTime; -extern bool s_bLastFrameDumped; +extern bool bLastFrameDumped; // Renderer really isn't a very good name for this class - it's more like "Misc". // The long term goal is to get rid of this class and replace it with others that make diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp index bbf2a966dd..368fec357c 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp @@ -43,6 +43,7 @@ #include "Television.h" #include "Host.h" #include "BPFunctions.h" +#include "AVIDump.h" namespace DX11 { @@ -62,6 +63,10 @@ ID3D11BlendState* resetblendstate = NULL; ID3D11DepthStencilState* resetdepthstate = NULL; ID3D11RasterizerState* resetraststate = NULL; +static ID3D11Texture2D* s_screenshot_texture = NULL; +static bool s_bAVIDumping; +static char *s_frame_data = NULL; + // GX pipeline state struct { @@ -296,9 +301,14 @@ void SetupDeviceObjects() hr = D3D::device->CreateRasterizerState(&rastdesc, &resetraststate); CHECK(hr==S_OK, "Create rasterizer state for Renderer::ResetAPIState"); D3D::SetDebugObjectName((ID3D11DeviceChild*)resetraststate, "rasterizer state for Renderer::ResetAPIState"); + + D3D11_TEXTURE2D_DESC scrtex_desc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, D3D::GetBackBufferWidth(), D3D::GetBackBufferHeight(), 1, 1, 0, D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ|D3D11_CPU_ACCESS_WRITE); + hr = D3D::device->CreateTexture2D(&scrtex_desc, NULL, &s_screenshot_texture); + CHECK(hr==S_OK, "Create screenshot staging texture"); + D3D::SetDebugObjectName((ID3D11DeviceChild*)s_screenshot_texture, "staging screenshot texture"); } -// Kill off all POOL_DEFAULT device objects. +// Kill off all device objects void TeardownDeviceObjects() { delete g_framebuffer_manager; @@ -314,6 +324,7 @@ void TeardownDeviceObjects() SAFE_RELEASE(resetblendstate); SAFE_RELEASE(resetdepthstate); SAFE_RELEASE(resetraststate); + SAFE_RELEASE(s_screenshot_texture); s_television.Shutdown(); } @@ -344,6 +355,10 @@ Renderer::Renderer() SetupDeviceObjects(); + bLastFrameDumped = false; + s_bAVIDumping = false; + + // Setup GX pipeline state memset(&gx_state.blenddc, 0, sizeof(gx_state.blenddc)); gx_state.blenddc.AlphaToCoverageEnable = FALSE; @@ -391,6 +406,15 @@ Renderer::Renderer() Renderer::~Renderer() { + if (g_ActiveConfig.bDumpFrames && bLastFrameDumped && s_bAVIDumping) + { + SAFE_DELETE_ARRAY(s_frame_data); + + AVIDump::Stop(); + s_bAVIDumping = false; + bLastFrameDumped = false; + } + TeardownDeviceObjects(); D3D::EndFrame(); D3D::Present(); @@ -835,15 +859,11 @@ void Renderer::SetBlendMode(bool forceUpdate) bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle &rc) { // copy back buffer to system memory - ID3D11Texture2D* buftex; - D3D11_TEXTURE2D_DESC tex_desc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, D3D::GetBackBufferWidth(), D3D::GetBackBufferHeight(), 1, 1, 0, D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ|D3D11_CPU_ACCESS_WRITE); - HRESULT hr = D3D::device->CreateTexture2D(&tex_desc, NULL, &buftex); - if (FAILED(hr)) PanicAlert("Failed to create screenshot buffer texture"); - D3D::context->CopyResource(buftex, (ID3D11Resource*)D3D::GetBackBuffer()->GetTex()); + D3D::context->CopyResource(s_screenshot_texture, (ID3D11Resource*)D3D::GetBackBuffer()->GetTex()); // D3DX11SaveTextureToFileA doesn't allow us to ignore the alpha channel, so we need to strip it out ourselves D3D11_MAPPED_SUBRESOURCE map; - D3D::context->Map(buftex, 0, D3D11_MAP_READ_WRITE, 0, &map); + D3D::context->Map(s_screenshot_texture, 0, D3D11_MAP_READ_WRITE, 0, &map); for (unsigned int y = 0; y < D3D::GetBackBufferHeight(); ++y) { u8* ptr = (u8*)map.pData + y * map.RowPitch + 3; @@ -853,21 +873,36 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle ptr += 4; } } - D3D::context->Unmap(buftex, 0); + D3D::context->Unmap(s_screenshot_texture, 0); // ready to be saved - hr = PD3DX11SaveTextureToFileA(D3D::context, buftex, D3DX11_IFF_PNG, filename.c_str()); - buftex->Release(); + HRESULT hr = PD3DX11SaveTextureToFileA(D3D::context, s_screenshot_texture, D3DX11_IFF_PNG, filename.c_str()); return SUCCEEDED(hr); } +void formatBufferDump(const char *in, char *out, int w, int h, int p) +{ + for (int y = 0; y < h; ++y) + { + const u32 *line = (u32*)(in + (h - y - 1) * p); + for (int x = 0; x < w; ++x) + { + memcpy(out, line, 3); + out += 3; + line += 4; + } + } +} // This function has the final picture. We adjust the aspect ratio here. void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,const EFBRectangle& rc,float Gamma) { if (g_bSkipCurrentFrame || (!XFBWrited && (!g_ActiveConfig.bUseXFB || !g_ActiveConfig.bUseRealXFB)) || !fbWidth || !fbHeight) { + if (g_ActiveConfig.bDumpFrames) + AVIDump::AddFrame(s_frame_data); + Core::Callback_VideoCopiedToXFB(false); return; } @@ -879,6 +914,9 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount); if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB) { + if (g_ActiveConfig.bDumpFrames) + AVIDump::AddFrame(s_frame_data); + Core::Callback_VideoCopiedToXFB(false); return; } @@ -984,6 +1022,63 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons s_bScreenshot = false; } + // Dump frames + static int w = 0, h = 0; + if (g_ActiveConfig.bDumpFrames) + { + static int s_recordWidth; + static int s_recordHeight; + + D3D::context->CopyResource(s_screenshot_texture, (ID3D11Resource*)D3D::GetBackBuffer()->GetTex()); + if (!bLastFrameDumped) + { + s_recordWidth = dst_rect.GetWidth(); + s_recordHeight = dst_rect.GetHeight(); + s_bAVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), s_recordWidth, s_recordHeight); + if (!s_bAVIDumping) + { + PanicAlert("Error dumping frames to AVI."); + } + else + { + char msg [255]; + sprintf_s(msg,255, "Dumping Frames to \"%sframedump0.avi\" (%dx%d RGB24)", + File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), s_recordWidth, s_recordHeight); + OSD::AddMessage(msg, 2000); + } + } + if (s_bAVIDumping) + { + D3D11_MAPPED_SUBRESOURCE map; + D3D::context->Map(s_screenshot_texture, 0, D3D11_MAP_READ, 0, &map); + + if (!s_frame_data || w != s_recordWidth || h != s_recordHeight) + { + delete[] s_frame_data; + s_frame_data = new char[3 * s_recordWidth * s_recordHeight]; + w = s_recordWidth; + h = s_recordHeight; + } + formatBufferDump((char*)map.pData, s_frame_data, s_recordWidth, s_recordHeight, map.RowPitch); + AVIDump::AddFrame(s_frame_data); + D3D::context->Unmap(s_screenshot_texture, 0); + } + bLastFrameDumped = true; + } + else + { + if (bLastFrameDumped && s_bAVIDumping) + { + SAFE_DELETE_ARRAY(s_frame_data); + w = h = 0; + + AVIDump::Stop(); + s_bAVIDumping = false; + OSD::AddMessage("Stop dumping frames to AVI", 2000); + } + bLastFrameDumped = false; + } + // Finish up the current frame, print some stats if (g_ActiveConfig.bShowFPS) { diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp index 15b592e800..e7177be396 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp @@ -60,12 +60,6 @@ namespace DX9 static int s_fps = 0; -static int s_recordWidth; -static int s_recordHeight; - -static bool s_bLastFrameDumped; -static bool s_bAVIDumping; - static u32 s_blendMode; static u32 s_LastAA; static bool IS_AMD; @@ -73,6 +67,7 @@ static bool IS_AMD; static char *st; static LPDIRECT3DSURFACE9 ScreenShootMEMSurface = NULL; +static bool s_bAVIDumping; // State translation lookup tables @@ -297,7 +292,7 @@ Renderer::Renderer() // Make sure to use valid texture sizes D3D::FixTextureSize(s_target_width, s_target_height); - s_bLastFrameDumped = false; + bLastFrameDumped = false; s_bAVIDumping = false; // We're not using fixed function. @@ -845,11 +840,11 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,const EFBRectangle& rc,float Gamma) { static char* data = 0; - static int w = 0, h = 0; if (g_bSkipCurrentFrame || (!XFBWrited && (!g_ActiveConfig.bUseXFB || !g_ActiveConfig.bUseRealXFB)) || !fbWidth || !fbHeight) { if (g_ActiveConfig.bDumpFrames && data) AVIDump::AddFrame(data); + Core::Callback_VideoCopiedToXFB(false); return; } @@ -862,6 +857,9 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount); if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB) { + if (g_ActiveConfig.bDumpFrames && data) + AVIDump::AddFrame(data); + Core::Callback_VideoCopiedToXFB(false); return; } @@ -1027,10 +1025,16 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons SaveScreenshot(s_sScreenshotName, dst_rect); s_bScreenshot = false; } + + // Dump frames + static int w = 0, h = 0; if (g_ActiveConfig.bDumpFrames) { + static int s_recordWidth; + static int s_recordHeight; + HRESULT hr = D3D::dev->GetRenderTargetData(D3D::GetBackBufferSurface(),ScreenShootMEMSurface); - if (!s_bLastFrameDumped) + if (!bLastFrameDumped) { s_recordWidth = dst_rect.GetWidth(); s_recordHeight = dst_rect.GetHeight(); @@ -1064,11 +1068,11 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons ScreenShootMEMSurface->UnlockRect(); } } - s_bLastFrameDumped = true; + bLastFrameDumped = true; } else { - if (s_bLastFrameDumped && s_bAVIDumping) + if (bLastFrameDumped && s_bAVIDumping) { if (data) { @@ -1080,7 +1084,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons s_bAVIDumping = false; OSD::AddMessage("Stop dumping frames to AVI", 2000); } - s_bLastFrameDumped = false; + bLastFrameDumped = false; } // Finish up the current frame, print some stats diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index ca3280673e..8b2d08eecc 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -521,7 +521,7 @@ Renderer::~Renderer() if(s_bAVIDumping) { AVIDump::Stop(); - s_bLastFrameDumped = false; + bLastFrameDumped = false; s_bAVIDumping = false; } #else @@ -970,11 +970,13 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB) { if (g_ActiveConfig.bDumpFrames && data) - #ifdef _WIN32 + { +#ifdef _WIN32 AVIDump::AddFrame((char *) data); - #elif defined HAVE_LIBAV +#elif defined HAVE_LIBAV AVIDump::AddFrame(data, w, h); - #endif +#endif + } Core::Callback_VideoCopiedToXFB(false); return; } @@ -1145,7 +1147,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons glReadPixels(dst_rect.left, dst_rect.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, data); if (GL_REPORT_ERROR() == GL_NO_ERROR && w > 0 && h > 0) { - if (!s_bLastFrameDumped) + if (!bLastFrameDumped) { #ifdef _WIN32 s_bAVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), w, h); @@ -1171,14 +1173,14 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons #endif } - s_bLastFrameDumped = true; + bLastFrameDumped = true; } else NOTICE_LOG(VIDEO, "Error reading framebuffer"); } else { - if (s_bLastFrameDumped && s_bAVIDumping) + if (bLastFrameDumped && s_bAVIDumping) { if (data) { @@ -1190,7 +1192,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons s_bAVIDumping = false; OSD::AddMessage("Stop dumping frames", 2000); } - s_bLastFrameDumped = false; + bLastFrameDumped = false; } #else if (g_ActiveConfig.bDumpFrames) From 5eb1e55f80a5c49270a7c7a5dfd625216a13abe2 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Thu, 8 Sep 2011 17:09:24 +0200 Subject: [PATCH 2/3] Merge some frame dumping code to VideoCommon, fixes a memory leak in D3D9 and OpenGL if emulation is stopped while dumping frames. Breaks D3D11 frame dumping for some weird reason (memory corruption or whatever?). --- Source/Core/VideoCommon/Src/RenderBase.cpp | 17 +++- Source/Core/VideoCommon/Src/RenderBase.h | 13 ++- .../Plugins/Plugin_VideoDX11/Src/Render.cpp | 44 +++------ Source/Plugins/Plugin_VideoDX9/Src/Render.cpp | 43 ++++----- Source/Plugins/Plugin_VideoOGL/Src/Render.cpp | 95 +++++++------------ 5 files changed, 93 insertions(+), 119 deletions(-) diff --git a/Source/Core/VideoCommon/Src/RenderBase.cpp b/Source/Core/VideoCommon/Src/RenderBase.cpp index 06f4c81ab6..fa6ba018c7 100644 --- a/Source/Core/VideoCommon/Src/RenderBase.cpp +++ b/Source/Core/VideoCommon/Src/RenderBase.cpp @@ -42,6 +42,7 @@ #include "Host.h" #include "XFMemory.h" #include "FifoPlayer/FifoRecorder.h" +#include "AVIDump.h" #include #include @@ -52,7 +53,6 @@ int OSDChoice, OSDTime; Renderer *g_renderer = NULL; -bool bLastFrameDumped = false; std::mutex Renderer::s_criticalScreenshot; std::string Renderer::s_sScreenshotName; @@ -81,15 +81,28 @@ bool Renderer::s_EnableDLCachingAfterRecording; unsigned int Renderer::prev_efb_format = (unsigned int)-1; -Renderer::Renderer() +Renderer::Renderer() : frame_data(NULL), bLastFrameDumped(false) { UpdateActiveConfig(); + +#if defined _WIN32 || defined HAVE_LIBAV + bAVIDumping = false; +#endif } Renderer::~Renderer() { // invalidate previous efb format prev_efb_format = (unsigned int)-1; + +#if defined _WIN32 || defined HAVE_LIBAV + if (g_ActiveConfig.bDumpFrames && bLastFrameDumped && bAVIDumping) + AVIDump::Stop(); +#else + if (f_pFrameDump.IsOpen()) + f_pFrameDump.Close(); +#endif + delete[] frame_data; } void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma) diff --git a/Source/Core/VideoCommon/Src/RenderBase.h b/Source/Core/VideoCommon/Src/RenderBase.h index 48f096851f..e8d4c55a20 100644 --- a/Source/Core/VideoCommon/Src/RenderBase.h +++ b/Source/Core/VideoCommon/Src/RenderBase.h @@ -132,9 +132,6 @@ public: protected: - static std::mutex s_criticalScreenshot; - static std::string s_sScreenshotName; - static void CalculateTargetScale(int x, int y, int &scaledX, int &scaledY); static bool CalculateTargetSize(int multiplier = 1); static void CalculateXYScale(const TargetRectangle& dst_rect); @@ -143,6 +140,16 @@ protected: static void RecordVideoMemory(); static volatile bool s_bScreenshot; + static std::mutex s_criticalScreenshot; + static std::string s_sScreenshotName; + +#if defined _WIN32 || defined HAVE_LIBAV + bool bAVIDumping; +#else + File::IOFile pFrameDump; +#endif + char* frame_data; + bool bLastFrameDumped; // The framebuffer size static int s_target_width; diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp index 368fec357c..9de763bf37 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp @@ -64,8 +64,6 @@ ID3D11DepthStencilState* resetdepthstate = NULL; ID3D11RasterizerState* resetraststate = NULL; static ID3D11Texture2D* s_screenshot_texture = NULL; -static bool s_bAVIDumping; -static char *s_frame_data = NULL; // GX pipeline state struct @@ -355,9 +353,6 @@ Renderer::Renderer() SetupDeviceObjects(); - bLastFrameDumped = false; - s_bAVIDumping = false; - // Setup GX pipeline state memset(&gx_state.blenddc, 0, sizeof(gx_state.blenddc)); @@ -406,15 +401,6 @@ Renderer::Renderer() Renderer::~Renderer() { - if (g_ActiveConfig.bDumpFrames && bLastFrameDumped && s_bAVIDumping) - { - SAFE_DELETE_ARRAY(s_frame_data); - - AVIDump::Stop(); - s_bAVIDumping = false; - bLastFrameDumped = false; - } - TeardownDeviceObjects(); D3D::EndFrame(); D3D::Present(); @@ -900,8 +886,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons { if (g_bSkipCurrentFrame || (!XFBWrited && (!g_ActiveConfig.bUseXFB || !g_ActiveConfig.bUseRealXFB)) || !fbWidth || !fbHeight) { - if (g_ActiveConfig.bDumpFrames) - AVIDump::AddFrame(s_frame_data); + if (g_ActiveConfig.bDumpFrames && frame_data) + AVIDump::AddFrame(frame_data); Core::Callback_VideoCopiedToXFB(false); return; @@ -914,8 +900,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount); if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB) { - if (g_ActiveConfig.bDumpFrames) - AVIDump::AddFrame(s_frame_data); + if (g_ActiveConfig.bDumpFrames && frame_data) + AVIDump::AddFrame(frame_data); Core::Callback_VideoCopiedToXFB(false); return; @@ -1034,8 +1020,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons { s_recordWidth = dst_rect.GetWidth(); s_recordHeight = dst_rect.GetHeight(); - s_bAVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), s_recordWidth, s_recordHeight); - if (!s_bAVIDumping) + bAVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), s_recordWidth, s_recordHeight); + if (!bAVIDumping) { PanicAlert("Error dumping frames to AVI."); } @@ -1047,33 +1033,33 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons OSD::AddMessage(msg, 2000); } } - if (s_bAVIDumping) + if (bAVIDumping) { D3D11_MAPPED_SUBRESOURCE map; D3D::context->Map(s_screenshot_texture, 0, D3D11_MAP_READ, 0, &map); - if (!s_frame_data || w != s_recordWidth || h != s_recordHeight) + if (!frame_data || w != s_recordWidth || h != s_recordHeight) { - delete[] s_frame_data; - s_frame_data = new char[3 * s_recordWidth * s_recordHeight]; + delete[] frame_data; + frame_data = new char[3 * s_recordWidth * s_recordHeight]; w = s_recordWidth; h = s_recordHeight; } - formatBufferDump((char*)map.pData, s_frame_data, s_recordWidth, s_recordHeight, map.RowPitch); - AVIDump::AddFrame(s_frame_data); + formatBufferDump((char*)map.pData, frame_data, s_recordWidth, s_recordHeight, map.RowPitch); + AVIDump::AddFrame(frame_data); D3D::context->Unmap(s_screenshot_texture, 0); } bLastFrameDumped = true; } else { - if (bLastFrameDumped && s_bAVIDumping) + if (bLastFrameDumped && bAVIDumping) { - SAFE_DELETE_ARRAY(s_frame_data); + SAFE_DELETE_ARRAY(frame_data); w = h = 0; AVIDump::Stop(); - s_bAVIDumping = false; + bAVIDumping = false; OSD::AddMessage("Stop dumping frames to AVI", 2000); } bLastFrameDumped = false; diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp index e7177be396..93b37e211a 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp @@ -67,7 +67,6 @@ static bool IS_AMD; static char *st; static LPDIRECT3DSURFACE9 ScreenShootMEMSurface = NULL; -static bool s_bAVIDumping; // State translation lookup tables @@ -292,9 +291,6 @@ Renderer::Renderer() // Make sure to use valid texture sizes D3D::FixTextureSize(s_target_width, s_target_height); - bLastFrameDumped = false; - s_bAVIDumping = false; - // We're not using fixed function. // Let's just set the matrices to identity to be sure. D3DXMATRIX mtx; @@ -337,10 +333,6 @@ Renderer::~Renderer() D3D::Present(); D3D::Close(); - if (s_bAVIDumping) - { - AVIDump::Stop(); - } delete[] st; } @@ -839,11 +831,10 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle // This function has the final picture. We adjust the aspect ratio here. void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,const EFBRectangle& rc,float Gamma) { - static char* data = 0; if (g_bSkipCurrentFrame || (!XFBWrited && (!g_ActiveConfig.bUseXFB || !g_ActiveConfig.bUseRealXFB)) || !fbWidth || !fbHeight) { - if (g_ActiveConfig.bDumpFrames && data) - AVIDump::AddFrame(data); + if (g_ActiveConfig.bDumpFrames && frame_data) + AVIDump::AddFrame(frame_data); Core::Callback_VideoCopiedToXFB(false); return; @@ -857,8 +848,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount); if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB) { - if (g_ActiveConfig.bDumpFrames && data) - AVIDump::AddFrame(data); + if (g_ActiveConfig.bDumpFrames && frame_data) + AVIDump::AddFrame(frame_data); Core::Callback_VideoCopiedToXFB(false); return; @@ -1038,8 +1029,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons { s_recordWidth = dst_rect.GetWidth(); s_recordHeight = dst_rect.GetHeight(); - s_bAVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), s_recordWidth, s_recordHeight); - if (!s_bAVIDumping) + bAVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), s_recordWidth, s_recordHeight); + if (!bAVIDumping) { PanicAlert("Error dumping frames to AVI."); } @@ -1051,20 +1042,20 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons OSD::AddMessage(msg, 2000); } } - if (s_bAVIDumping) + if (bAVIDumping) { D3DLOCKED_RECT rect; if (SUCCEEDED(ScreenShootMEMSurface->LockRect(&rect, dst_rect.AsRECT(), D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_NOSYSLOCK | D3DLOCK_READONLY))) { - if (!data || w != s_recordWidth || h != s_recordHeight) + if (!frame_data || w != s_recordWidth || h != s_recordHeight) { - free(data); - data = (char*)malloc(3 * s_recordWidth * s_recordHeight); + delete[] frame_data; + frame_data = new char[3 * s_recordWidth * s_recordHeight]; w = s_recordWidth; h = s_recordHeight; } - formatBufferDump((const char*)rect.pBits, data, s_recordWidth, s_recordHeight, rect.Pitch); - AVIDump::AddFrame(data); + formatBufferDump((const char*)rect.pBits, frame_data, s_recordWidth, s_recordHeight, rect.Pitch); + AVIDump::AddFrame(frame_data); ScreenShootMEMSurface->UnlockRect(); } } @@ -1072,16 +1063,16 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons } else { - if (bLastFrameDumped && s_bAVIDumping) + if (bLastFrameDumped && bAVIDumping) { - if (data) + if (frame_data) { - free(data); - data = 0; + delete[] frame_data; + frame_data = 0; w = h = 0; } AVIDump::Stop(); - s_bAVIDumping = false; + bAVIDumping = false; OSD::AddMessage("Stop dumping frames to AVI", 2000); } bLastFrameDumped = false; diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index 8b2d08eecc..415d1986b3 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -110,12 +110,6 @@ int s_fps=0; RasterFont* s_pfont = NULL; -#if defined _WIN32 || defined HAVE_LIBAV -static bool s_bAVIDumping = false; -#else -static File::IOFile f_pFrameDump; -#endif - // 1 for no MSAA. Use s_MSAASamples > 1 to check for MSAA. static int s_MSAASamples = 1; static int s_MSAACoverageSamples = 0; @@ -250,9 +244,6 @@ Renderer::Renderer() s_fps=0; s_blendMode = 0; -#if defined _WIN32 || defined HAVE_LIBAV - s_bAVIDumping = false; -#endif #if defined HAVE_CG && HAVE_CG g_cgcontext = cgCreateContext(); @@ -516,19 +507,6 @@ Renderer::~Renderer() #endif delete g_framebuffer_manager; - -#if defined _WIN32 || defined HAVE_LIBAV - if(s_bAVIDumping) - { - AVIDump::Stop(); - bLastFrameDumped = false; - s_bAVIDumping = false; - } -#else - if (f_pFrameDump.IsOpen()) - f_pFrameDump.Close(); - s_bLastFrameDumped = false; -#endif } // Create On-Screen-Messages @@ -947,15 +925,14 @@ void Renderer::SetBlendMode(bool forceUpdate) // This function has the final picture. We adjust the aspect ratio here. void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,const EFBRectangle& rc,float Gamma) { - static u8 *data = NULL; static int w = 0, h = 0; if (g_bSkipCurrentFrame || (!XFBWrited && (!g_ActiveConfig.bUseXFB || !g_ActiveConfig.bUseRealXFB)) || !fbWidth || !fbHeight) { - if (g_ActiveConfig.bDumpFrames && data) + if (g_ActiveConfig.bDumpFrames && frame_data) #ifdef _WIN32 - AVIDump::AddFrame((char *) data); + AVIDump::AddFrame(frame_data); #elif defined HAVE_LIBAV - AVIDump::AddFrame(data, w, h); + AVIDump::AddFrame(frame_data, w, h); #endif Core::Callback_VideoCopiedToXFB(false); return; @@ -969,12 +946,12 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount); if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB) { - if (g_ActiveConfig.bDumpFrames && data) + if (g_ActiveConfig.bDumpFrames && frame_data) { #ifdef _WIN32 - AVIDump::AddFrame((char *) data); + AVIDump::AddFrame(frame_data); #elif defined HAVE_LIBAV - AVIDump::AddFrame(data, w, h); + AVIDump::AddFrame(frame_data, w, h); #endif } Core::Callback_VideoCopiedToXFB(false); @@ -1135,26 +1112,26 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons if (g_ActiveConfig.bDumpFrames) { std::lock_guard lk(s_criticalScreenshot); - if (!data || w != dst_rect.GetWidth() || + if (!frame_data || w != dst_rect.GetWidth() || h != dst_rect.GetHeight()) { - if (data) delete[] data; + if (frame_data) delete[] frame_data; w = dst_rect.GetWidth(); h = dst_rect.GetHeight(); - data = new u8[3 * w * h]; + frame_data = new char[3 * w * h]; } glPixelStorei(GL_PACK_ALIGNMENT, 1); - glReadPixels(dst_rect.left, dst_rect.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, data); + glReadPixels(dst_rect.left, dst_rect.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, frame_data); if (GL_REPORT_ERROR() == GL_NO_ERROR && w > 0 && h > 0) { if (!bLastFrameDumped) { #ifdef _WIN32 - s_bAVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), w, h); + bAVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), w, h); #else - s_bAVIDumping = AVIDump::Start(w, h); + bAVIDumping = AVIDump::Start(w, h); #endif - if (!s_bAVIDumping) + if (!bAVIDumping) OSD::AddMessage("AVIDump Start failed", 2000); else { @@ -1163,13 +1140,13 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), w, h).c_str(), 2000); } } - if (s_bAVIDumping) + if (bAVIDumping) { #ifdef _WIN32 - AVIDump::AddFrame((char *) data); + AVIDump::AddFrame(frame_data); #else - FlipImageData(data, w, h); - AVIDump::AddFrame(data, w, h); + FlipImageData(frame_data, w, h); + AVIDump::AddFrame(frame_data, w, h); #endif } @@ -1180,16 +1157,16 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons } else { - if (bLastFrameDumped && s_bAVIDumping) + if (bLastFrameDumped && bAVIDumping) { - if (data) + if (frame_data) { - delete[] data; - data = NULL; + delete[] frame_data; + frame_data = NULL; w = h = 0; } AVIDump::Stop(); - s_bAVIDumping = false; + bAVIDumping = false; OSD::AddMessage("Stop dumping frames", 2000); } bLastFrameDumped = false; @@ -1201,16 +1178,16 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons std::string movie_file_name; w = dst_rect.GetWidth(); h = dst_rect.GetHeight(); - data = new u8[3 * w * h]; + frame_data = new u8[3 * w * h]; glPixelStorei(GL_PACK_ALIGNMENT, 1); - glReadPixels(dst_rect.left, dst_rect.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, data); + glReadPixels(dst_rect.left, dst_rect.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, frame_data); if (GL_REPORT_ERROR() == GL_NO_ERROR) { - if (!s_bLastFrameDumped) + if (!bLastFrameDumped) { movie_file_name = File::GetUserPath(D_DUMPFRAMES_IDX) + "framedump.raw"; - f_pFrameDump.Open(movie_file_name, "wb"); - if (!f_pFrameDump) + pFrameDump.Open(movie_file_name, "wb"); + if (!pFrameDump) OSD::AddMessage("Error opening framedump.raw for writing.", 2000); else { @@ -1219,22 +1196,22 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons OSD::AddMessage(msg, 2000); } } - if (f_pFrameDump) + if (pFrameDump) { - FlipImageData(data, w, h); - f_pFrameDump.WriteBytes(data, w * 3 * h); - f_pFrameDump.Flush(); + FlipImageData(frame_data, w, h); + pFrameDump.WriteBytes(frame_data, w * 3 * h); + pFrameDump.Flush(); } - s_bLastFrameDumped = true; + bLastFrameDumped = true; } - delete[] data; + delete[] frame_data; } else { - if (s_bLastFrameDumped) - f_pFrameDump.Close(); - s_bLastFrameDumped = false; + if (bLastFrameDumped) + pFrameDump.Close(); + bLastFrameDumped = false; } #endif From 3802201fb7ae6defb3614973ff01e1cfa8c38d6c Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Thu, 8 Sep 2011 17:52:01 +0200 Subject: [PATCH 3/3] Fix D3D11 frame dumping. --- Source/Plugins/Plugin_VideoDX11/Src/Render.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp index 9de763bf37..53cf9fd4d9 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp @@ -871,13 +871,15 @@ void formatBufferDump(const char *in, char *out, int w, int h, int p) { for (int y = 0; y < h; ++y) { - const u32 *line = (u32*)(in + (h - y - 1) * p); + const u8 *line = (u8*)(in + (h - y - 1) * p); for (int x = 0; x < w; ++x) { - memcpy(out, line, 3); + out[0] = line[2]; + out[1] = line[1]; + out[2] = line[0]; out += 3; line += 4; - } + } } } @@ -1045,7 +1047,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons w = s_recordWidth; h = s_recordHeight; } - formatBufferDump((char*)map.pData, frame_data, s_recordWidth, s_recordHeight, map.RowPitch); + char* source_ptr = (char*)map.pData + dst_rect.left*4 + dst_rect.top*map.RowPitch; + formatBufferDump(source_ptr, frame_data, s_recordWidth, s_recordHeight, map.RowPitch); AVIDump::AddFrame(frame_data); D3D::context->Unmap(s_screenshot_texture, 0); }