Merge remote-tracking branch 'remotes/origin/d3d11-frame-dumping'

This commit is contained in:
NeoBrainX 2011-09-08 22:06:12 +02:00
commit 063660e409
5 changed files with 192 additions and 114 deletions

View File

@ -42,6 +42,7 @@
#include "Host.h" #include "Host.h"
#include "XFMemory.h" #include "XFMemory.h"
#include "FifoPlayer/FifoRecorder.h" #include "FifoPlayer/FifoRecorder.h"
#include "AVIDump.h"
#include <cmath> #include <cmath>
#include <string> #include <string>
@ -52,7 +53,6 @@ int OSDChoice, OSDTime;
Renderer *g_renderer = NULL; Renderer *g_renderer = NULL;
bool s_bLastFrameDumped = false;
std::mutex Renderer::s_criticalScreenshot; std::mutex Renderer::s_criticalScreenshot;
std::string Renderer::s_sScreenshotName; std::string Renderer::s_sScreenshotName;
@ -81,15 +81,28 @@ bool Renderer::s_EnableDLCachingAfterRecording;
unsigned int Renderer::prev_efb_format = (unsigned int)-1; unsigned int Renderer::prev_efb_format = (unsigned int)-1;
Renderer::Renderer() Renderer::Renderer() : frame_data(NULL), bLastFrameDumped(false)
{ {
UpdateActiveConfig(); UpdateActiveConfig();
#if defined _WIN32 || defined HAVE_LIBAV
bAVIDumping = false;
#endif
} }
Renderer::~Renderer() Renderer::~Renderer()
{ {
// invalidate previous efb format // invalidate previous efb format
prev_efb_format = (unsigned int)-1; 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) void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma)

View File

@ -41,7 +41,7 @@
extern int frameCount; extern int frameCount;
extern int OSDChoice, OSDTime; 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". // 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 // The long term goal is to get rid of this class and replace it with others that make
@ -132,9 +132,6 @@ public:
protected: protected:
static std::mutex s_criticalScreenshot;
static std::string s_sScreenshotName;
static void CalculateTargetScale(int x, int y, int &scaledX, int &scaledY); static void CalculateTargetScale(int x, int y, int &scaledX, int &scaledY);
static bool CalculateTargetSize(int multiplier = 1); static bool CalculateTargetSize(int multiplier = 1);
static void CalculateXYScale(const TargetRectangle& dst_rect); static void CalculateXYScale(const TargetRectangle& dst_rect);
@ -143,6 +140,16 @@ protected:
static void RecordVideoMemory(); static void RecordVideoMemory();
static volatile bool s_bScreenshot; 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 // The framebuffer size
static int s_target_width; static int s_target_width;

View File

@ -43,6 +43,7 @@
#include "Television.h" #include "Television.h"
#include "Host.h" #include "Host.h"
#include "BPFunctions.h" #include "BPFunctions.h"
#include "AVIDump.h"
namespace DX11 namespace DX11
{ {
@ -62,6 +63,8 @@ ID3D11BlendState* resetblendstate = NULL;
ID3D11DepthStencilState* resetdepthstate = NULL; ID3D11DepthStencilState* resetdepthstate = NULL;
ID3D11RasterizerState* resetraststate = NULL; ID3D11RasterizerState* resetraststate = NULL;
static ID3D11Texture2D* s_screenshot_texture = NULL;
// GX pipeline state // GX pipeline state
struct struct
{ {
@ -296,9 +299,14 @@ void SetupDeviceObjects()
hr = D3D::device->CreateRasterizerState(&rastdesc, &resetraststate); hr = D3D::device->CreateRasterizerState(&rastdesc, &resetraststate);
CHECK(hr==S_OK, "Create rasterizer state for Renderer::ResetAPIState"); CHECK(hr==S_OK, "Create rasterizer state for Renderer::ResetAPIState");
D3D::SetDebugObjectName((ID3D11DeviceChild*)resetraststate, "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() void TeardownDeviceObjects()
{ {
delete g_framebuffer_manager; delete g_framebuffer_manager;
@ -314,6 +322,7 @@ void TeardownDeviceObjects()
SAFE_RELEASE(resetblendstate); SAFE_RELEASE(resetblendstate);
SAFE_RELEASE(resetdepthstate); SAFE_RELEASE(resetdepthstate);
SAFE_RELEASE(resetraststate); SAFE_RELEASE(resetraststate);
SAFE_RELEASE(s_screenshot_texture);
s_television.Shutdown(); s_television.Shutdown();
} }
@ -344,6 +353,7 @@ Renderer::Renderer()
SetupDeviceObjects(); SetupDeviceObjects();
// Setup GX pipeline state // Setup GX pipeline state
memset(&gx_state.blenddc, 0, sizeof(gx_state.blenddc)); memset(&gx_state.blenddc, 0, sizeof(gx_state.blenddc));
gx_state.blenddc.AlphaToCoverageEnable = FALSE; gx_state.blenddc.AlphaToCoverageEnable = FALSE;
@ -835,15 +845,11 @@ void Renderer::SetBlendMode(bool forceUpdate)
bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle &rc) bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle &rc)
{ {
// copy back buffer to system memory // copy back buffer to system memory
ID3D11Texture2D* buftex; D3D::context->CopyResource(s_screenshot_texture, (ID3D11Resource*)D3D::GetBackBuffer()->GetTex());
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());
// D3DX11SaveTextureToFileA doesn't allow us to ignore the alpha channel, so we need to strip it out ourselves // D3DX11SaveTextureToFileA doesn't allow us to ignore the alpha channel, so we need to strip it out ourselves
D3D11_MAPPED_SUBRESOURCE map; 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) for (unsigned int y = 0; y < D3D::GetBackBufferHeight(); ++y)
{ {
u8* ptr = (u8*)map.pData + y * map.RowPitch + 3; u8* ptr = (u8*)map.pData + y * map.RowPitch + 3;
@ -853,21 +859,38 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle
ptr += 4; ptr += 4;
} }
} }
D3D::context->Unmap(buftex, 0); D3D::context->Unmap(s_screenshot_texture, 0);
// ready to be saved // ready to be saved
hr = PD3DX11SaveTextureToFileA(D3D::context, buftex, D3DX11_IFF_PNG, filename.c_str()); HRESULT hr = PD3DX11SaveTextureToFileA(D3D::context, s_screenshot_texture, D3DX11_IFF_PNG, filename.c_str());
buftex->Release();
return SUCCEEDED(hr); return SUCCEEDED(hr);
} }
void formatBufferDump(const char *in, char *out, int w, int h, int p)
{
for (int y = 0; y < h; ++y)
{
const u8 *line = (u8*)(in + (h - y - 1) * p);
for (int x = 0; x < w; ++x)
{
out[0] = line[2];
out[1] = line[1];
out[2] = line[0];
out += 3;
line += 4;
}
}
}
// This function has the final picture. We adjust the aspect ratio here. // 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) 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_bSkipCurrentFrame || (!XFBWrited && (!g_ActiveConfig.bUseXFB || !g_ActiveConfig.bUseRealXFB)) || !fbWidth || !fbHeight)
{ {
if (g_ActiveConfig.bDumpFrames && frame_data)
AVIDump::AddFrame(frame_data);
Core::Callback_VideoCopiedToXFB(false); Core::Callback_VideoCopiedToXFB(false);
return; return;
} }
@ -879,6 +902,9 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount); const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB) if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB)
{ {
if (g_ActiveConfig.bDumpFrames && frame_data)
AVIDump::AddFrame(frame_data);
Core::Callback_VideoCopiedToXFB(false); Core::Callback_VideoCopiedToXFB(false);
return; return;
} }
@ -984,6 +1010,64 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
s_bScreenshot = false; 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();
bAVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), s_recordWidth, s_recordHeight);
if (!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 (bAVIDumping)
{
D3D11_MAPPED_SUBRESOURCE map;
D3D::context->Map(s_screenshot_texture, 0, D3D11_MAP_READ, 0, &map);
if (!frame_data || w != s_recordWidth || h != s_recordHeight)
{
delete[] frame_data;
frame_data = new char[3 * s_recordWidth * s_recordHeight];
w = s_recordWidth;
h = s_recordHeight;
}
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);
}
bLastFrameDumped = true;
}
else
{
if (bLastFrameDumped && bAVIDumping)
{
SAFE_DELETE_ARRAY(frame_data);
w = h = 0;
AVIDump::Stop();
bAVIDumping = false;
OSD::AddMessage("Stop dumping frames to AVI", 2000);
}
bLastFrameDumped = false;
}
// Finish up the current frame, print some stats // Finish up the current frame, print some stats
if (g_ActiveConfig.bShowFPS) if (g_ActiveConfig.bShowFPS)
{ {

View File

@ -60,12 +60,6 @@ namespace DX9
static int s_fps = 0; 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_blendMode;
static u32 s_LastAA; static u32 s_LastAA;
static bool IS_AMD; static bool IS_AMD;
@ -297,9 +291,6 @@ Renderer::Renderer()
// Make sure to use valid texture sizes // Make sure to use valid texture sizes
D3D::FixTextureSize(s_target_width, s_target_height); D3D::FixTextureSize(s_target_width, s_target_height);
s_bLastFrameDumped = false;
s_bAVIDumping = false;
// We're not using fixed function. // We're not using fixed function.
// Let's just set the matrices to identity to be sure. // Let's just set the matrices to identity to be sure.
D3DXMATRIX mtx; D3DXMATRIX mtx;
@ -342,10 +333,6 @@ Renderer::~Renderer()
D3D::Present(); D3D::Present();
D3D::Close(); D3D::Close();
if (s_bAVIDumping)
{
AVIDump::Stop();
}
delete[] st; delete[] st;
} }
@ -844,12 +831,11 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle
// This function has the final picture. We adjust the aspect ratio here. // 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) 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_bSkipCurrentFrame || (!XFBWrited && (!g_ActiveConfig.bUseXFB || !g_ActiveConfig.bUseRealXFB)) || !fbWidth || !fbHeight)
{ {
if (g_ActiveConfig.bDumpFrames && data) if (g_ActiveConfig.bDumpFrames && frame_data)
AVIDump::AddFrame(data); AVIDump::AddFrame(frame_data);
Core::Callback_VideoCopiedToXFB(false); Core::Callback_VideoCopiedToXFB(false);
return; return;
} }
@ -862,6 +848,9 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount); const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB) if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB)
{ {
if (g_ActiveConfig.bDumpFrames && frame_data)
AVIDump::AddFrame(frame_data);
Core::Callback_VideoCopiedToXFB(false); Core::Callback_VideoCopiedToXFB(false);
return; return;
} }
@ -1027,15 +1016,21 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
SaveScreenshot(s_sScreenshotName, dst_rect); SaveScreenshot(s_sScreenshotName, dst_rect);
s_bScreenshot = false; s_bScreenshot = false;
} }
// Dump frames
static int w = 0, h = 0;
if (g_ActiveConfig.bDumpFrames) if (g_ActiveConfig.bDumpFrames)
{ {
static int s_recordWidth;
static int s_recordHeight;
HRESULT hr = D3D::dev->GetRenderTargetData(D3D::GetBackBufferSurface(),ScreenShootMEMSurface); HRESULT hr = D3D::dev->GetRenderTargetData(D3D::GetBackBufferSurface(),ScreenShootMEMSurface);
if (!s_bLastFrameDumped) if (!bLastFrameDumped)
{ {
s_recordWidth = dst_rect.GetWidth(); s_recordWidth = dst_rect.GetWidth();
s_recordHeight = dst_rect.GetHeight(); s_recordHeight = dst_rect.GetHeight();
s_bAVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), s_recordWidth, s_recordHeight); bAVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), s_recordWidth, s_recordHeight);
if (!s_bAVIDumping) if (!bAVIDumping)
{ {
PanicAlert("Error dumping frames to AVI."); PanicAlert("Error dumping frames to AVI.");
} }
@ -1047,40 +1042,40 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
OSD::AddMessage(msg, 2000); OSD::AddMessage(msg, 2000);
} }
} }
if (s_bAVIDumping) if (bAVIDumping)
{ {
D3DLOCKED_RECT rect; D3DLOCKED_RECT rect;
if (SUCCEEDED(ScreenShootMEMSurface->LockRect(&rect, dst_rect.AsRECT(), D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_NOSYSLOCK | D3DLOCK_READONLY))) 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); delete[] frame_data;
data = (char*)malloc(3 * s_recordWidth * s_recordHeight); frame_data = new char[3 * s_recordWidth * s_recordHeight];
w = s_recordWidth; w = s_recordWidth;
h = s_recordHeight; h = s_recordHeight;
} }
formatBufferDump((const char*)rect.pBits, data, s_recordWidth, s_recordHeight, rect.Pitch); formatBufferDump((const char*)rect.pBits, frame_data, s_recordWidth, s_recordHeight, rect.Pitch);
AVIDump::AddFrame(data); AVIDump::AddFrame(frame_data);
ScreenShootMEMSurface->UnlockRect(); ScreenShootMEMSurface->UnlockRect();
} }
} }
s_bLastFrameDumped = true; bLastFrameDumped = true;
} }
else else
{ {
if (s_bLastFrameDumped && s_bAVIDumping) if (bLastFrameDumped && bAVIDumping)
{ {
if (data) if (frame_data)
{ {
free(data); delete[] frame_data;
data = 0; frame_data = 0;
w = h = 0; w = h = 0;
} }
AVIDump::Stop(); AVIDump::Stop();
s_bAVIDumping = false; bAVIDumping = false;
OSD::AddMessage("Stop dumping frames to AVI", 2000); OSD::AddMessage("Stop dumping frames to AVI", 2000);
} }
s_bLastFrameDumped = false; bLastFrameDumped = false;
} }
// Finish up the current frame, print some stats // Finish up the current frame, print some stats

View File

@ -110,12 +110,6 @@ int s_fps=0;
RasterFont* s_pfont = NULL; 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. // 1 for no MSAA. Use s_MSAASamples > 1 to check for MSAA.
static int s_MSAASamples = 1; static int s_MSAASamples = 1;
static int s_MSAACoverageSamples = 0; static int s_MSAACoverageSamples = 0;
@ -250,9 +244,6 @@ Renderer::Renderer()
s_fps=0; s_fps=0;
s_blendMode = 0; s_blendMode = 0;
#if defined _WIN32 || defined HAVE_LIBAV
s_bAVIDumping = false;
#endif
#if defined HAVE_CG && HAVE_CG #if defined HAVE_CG && HAVE_CG
g_cgcontext = cgCreateContext(); g_cgcontext = cgCreateContext();
@ -516,19 +507,6 @@ Renderer::~Renderer()
#endif #endif
delete g_framebuffer_manager; delete g_framebuffer_manager;
#if defined _WIN32 || defined HAVE_LIBAV
if(s_bAVIDumping)
{
AVIDump::Stop();
s_bLastFrameDumped = false;
s_bAVIDumping = false;
}
#else
if (f_pFrameDump.IsOpen())
f_pFrameDump.Close();
s_bLastFrameDumped = false;
#endif
} }
// Create On-Screen-Messages // 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. // 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) 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; static int w = 0, h = 0;
if (g_bSkipCurrentFrame || (!XFBWrited && (!g_ActiveConfig.bUseXFB || !g_ActiveConfig.bUseRealXFB)) || !fbWidth || !fbHeight) 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 #ifdef _WIN32
AVIDump::AddFrame((char *) data); AVIDump::AddFrame(frame_data);
#elif defined HAVE_LIBAV #elif defined HAVE_LIBAV
AVIDump::AddFrame(data, w, h); AVIDump::AddFrame(frame_data, w, h);
#endif #endif
Core::Callback_VideoCopiedToXFB(false); Core::Callback_VideoCopiedToXFB(false);
return; return;
@ -969,12 +946,14 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount); const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB) 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); #ifdef _WIN32
#elif defined HAVE_LIBAV AVIDump::AddFrame(frame_data);
AVIDump::AddFrame(data, w, h); #elif defined HAVE_LIBAV
#endif AVIDump::AddFrame(frame_data, w, h);
#endif
}
Core::Callback_VideoCopiedToXFB(false); Core::Callback_VideoCopiedToXFB(false);
return; return;
} }
@ -1133,26 +1112,26 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
if (g_ActiveConfig.bDumpFrames) if (g_ActiveConfig.bDumpFrames)
{ {
std::lock_guard<std::mutex> lk(s_criticalScreenshot); std::lock_guard<std::mutex> lk(s_criticalScreenshot);
if (!data || w != dst_rect.GetWidth() || if (!frame_data || w != dst_rect.GetWidth() ||
h != dst_rect.GetHeight()) h != dst_rect.GetHeight())
{ {
if (data) delete[] data; if (frame_data) delete[] frame_data;
w = dst_rect.GetWidth(); w = dst_rect.GetWidth();
h = dst_rect.GetHeight(); h = dst_rect.GetHeight();
data = new u8[3 * w * h]; frame_data = new char[3 * w * h];
} }
glPixelStorei(GL_PACK_ALIGNMENT, 1); 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 (GL_REPORT_ERROR() == GL_NO_ERROR && w > 0 && h > 0)
{ {
if (!s_bLastFrameDumped) if (!bLastFrameDumped)
{ {
#ifdef _WIN32 #ifdef _WIN32
s_bAVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), w, h); bAVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), w, h);
#else #else
s_bAVIDumping = AVIDump::Start(w, h); bAVIDumping = AVIDump::Start(w, h);
#endif #endif
if (!s_bAVIDumping) if (!bAVIDumping)
OSD::AddMessage("AVIDump Start failed", 2000); OSD::AddMessage("AVIDump Start failed", 2000);
else else
{ {
@ -1161,36 +1140,36 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), w, h).c_str(), 2000); File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), w, h).c_str(), 2000);
} }
} }
if (s_bAVIDumping) if (bAVIDumping)
{ {
#ifdef _WIN32 #ifdef _WIN32
AVIDump::AddFrame((char *) data); AVIDump::AddFrame(frame_data);
#else #else
FlipImageData(data, w, h); FlipImageData(frame_data, w, h);
AVIDump::AddFrame(data, w, h); AVIDump::AddFrame(frame_data, w, h);
#endif #endif
} }
s_bLastFrameDumped = true; bLastFrameDumped = true;
} }
else else
NOTICE_LOG(VIDEO, "Error reading framebuffer"); NOTICE_LOG(VIDEO, "Error reading framebuffer");
} }
else else
{ {
if (s_bLastFrameDumped && s_bAVIDumping) if (bLastFrameDumped && bAVIDumping)
{ {
if (data) if (frame_data)
{ {
delete[] data; delete[] frame_data;
data = NULL; frame_data = NULL;
w = h = 0; w = h = 0;
} }
AVIDump::Stop(); AVIDump::Stop();
s_bAVIDumping = false; bAVIDumping = false;
OSD::AddMessage("Stop dumping frames", 2000); OSD::AddMessage("Stop dumping frames", 2000);
} }
s_bLastFrameDumped = false; bLastFrameDumped = false;
} }
#else #else
if (g_ActiveConfig.bDumpFrames) if (g_ActiveConfig.bDumpFrames)
@ -1199,16 +1178,16 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
std::string movie_file_name; std::string movie_file_name;
w = dst_rect.GetWidth(); w = dst_rect.GetWidth();
h = dst_rect.GetHeight(); h = dst_rect.GetHeight();
data = new u8[3 * w * h]; frame_data = new u8[3 * w * h];
glPixelStorei(GL_PACK_ALIGNMENT, 1); 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 (GL_REPORT_ERROR() == GL_NO_ERROR)
{ {
if (!s_bLastFrameDumped) if (!bLastFrameDumped)
{ {
movie_file_name = File::GetUserPath(D_DUMPFRAMES_IDX) + "framedump.raw"; movie_file_name = File::GetUserPath(D_DUMPFRAMES_IDX) + "framedump.raw";
f_pFrameDump.Open(movie_file_name, "wb"); pFrameDump.Open(movie_file_name, "wb");
if (!f_pFrameDump) if (!pFrameDump)
OSD::AddMessage("Error opening framedump.raw for writing.", 2000); OSD::AddMessage("Error opening framedump.raw for writing.", 2000);
else else
{ {
@ -1217,22 +1196,22 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
OSD::AddMessage(msg, 2000); OSD::AddMessage(msg, 2000);
} }
} }
if (f_pFrameDump) if (pFrameDump)
{ {
FlipImageData(data, w, h); FlipImageData(frame_data, w, h);
f_pFrameDump.WriteBytes(data, w * 3 * h); pFrameDump.WriteBytes(frame_data, w * 3 * h);
f_pFrameDump.Flush(); pFrameDump.Flush();
} }
s_bLastFrameDumped = true; bLastFrameDumped = true;
} }
delete[] data; delete[] frame_data;
} }
else else
{ {
if (s_bLastFrameDumped) if (bLastFrameDumped)
f_pFrameDump.Close(); pFrameDump.Close();
s_bLastFrameDumped = false; bLastFrameDumped = false;
} }
#endif #endif