AVIDump: Move CoreTiming into caller.
This commit is contained in:
parent
a583d36c7f
commit
9f264c0872
|
@ -119,7 +119,7 @@ static void IPC_HLE_UpdateCallback(u64 userdata, s64 cyclesLate)
|
||||||
|
|
||||||
static void VICallback(u64 userdata, s64 cyclesLate)
|
static void VICallback(u64 userdata, s64 cyclesLate)
|
||||||
{
|
{
|
||||||
VideoInterface::Update();
|
VideoInterface::Update(CoreTiming::GetTicks() - cyclesLate);
|
||||||
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerHalfLine() - cyclesLate, et_VI);
|
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerHalfLine() - cyclesLate, et_VI);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -638,7 +638,7 @@ u32 GetTicksPerField()
|
||||||
return GetTicksPerEvenField();
|
return GetTicksPerEvenField();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void BeginField(FieldType field)
|
static void BeginField(FieldType field, u64 ticks)
|
||||||
{
|
{
|
||||||
// Could we fit a second line of data in the stride?
|
// Could we fit a second line of data in the stride?
|
||||||
bool potentially_interlaced_xfb =
|
bool potentially_interlaced_xfb =
|
||||||
|
@ -707,7 +707,7 @@ static void BeginField(FieldType field)
|
||||||
// To correctly handle that case we would need to collate all changes
|
// To correctly handle that case we would need to collate all changes
|
||||||
// to VI during scanout and delay outputting the frame till then.
|
// to VI during scanout and delay outputting the frame till then.
|
||||||
if (xfbAddr)
|
if (xfbAddr)
|
||||||
g_video_backend->Video_BeginField(xfbAddr, fbWidth, fbStride, fbHeight);
|
g_video_backend->Video_BeginField(xfbAddr, fbWidth, fbStride, fbHeight, ticks);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void EndField()
|
static void EndField()
|
||||||
|
@ -717,7 +717,7 @@ static void EndField()
|
||||||
|
|
||||||
// Purpose: Send VI interrupt when triggered
|
// Purpose: Send VI interrupt when triggered
|
||||||
// Run when: When a frame is scanned (progressive/interlace)
|
// Run when: When a frame is scanned (progressive/interlace)
|
||||||
void Update()
|
void Update(u64 ticks)
|
||||||
{
|
{
|
||||||
if (s_half_line_of_next_si_poll == s_half_line_count)
|
if (s_half_line_of_next_si_poll == s_half_line_count)
|
||||||
{
|
{
|
||||||
|
@ -726,11 +726,11 @@ void Update()
|
||||||
}
|
}
|
||||||
if (s_half_line_count == s_even_field_first_hl)
|
if (s_half_line_count == s_even_field_first_hl)
|
||||||
{
|
{
|
||||||
BeginField(FIELD_EVEN);
|
BeginField(FIELD_EVEN, ticks);
|
||||||
}
|
}
|
||||||
else if (s_half_line_count == s_odd_field_first_hl)
|
else if (s_half_line_count == s_odd_field_first_hl)
|
||||||
{
|
{
|
||||||
BeginField(FIELD_ODD);
|
BeginField(FIELD_ODD, ticks);
|
||||||
}
|
}
|
||||||
else if (s_half_line_count == s_even_field_last_hl)
|
else if (s_half_line_count == s_even_field_last_hl)
|
||||||
{
|
{
|
||||||
|
|
|
@ -337,7 +337,7 @@ u32 GetXFBAddressTop();
|
||||||
u32 GetXFBAddressBottom();
|
u32 GetXFBAddressBottom();
|
||||||
|
|
||||||
// Update and draw framebuffer
|
// Update and draw framebuffer
|
||||||
void Update();
|
void Update(u64 ticks);
|
||||||
|
|
||||||
// UpdateInterrupts: check if we have to generate a new VI Interrupt
|
// UpdateInterrupts: check if we have to generate a new VI Interrupt
|
||||||
void UpdateInterrupts();
|
void UpdateInterrupts();
|
||||||
|
|
|
@ -713,7 +713,7 @@ 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::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
|
void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
|
||||||
const EFBRectangle& rc, float Gamma)
|
const EFBRectangle& rc, u64 ticks, float Gamma)
|
||||||
{
|
{
|
||||||
if ((!XFBWrited && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight)
|
if ((!XFBWrited && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight)
|
||||||
{
|
{
|
||||||
|
@ -824,8 +824,8 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
|
||||||
D3D11_MAPPED_SUBRESOURCE map;
|
D3D11_MAPPED_SUBRESOURCE map;
|
||||||
D3D::context->Map(s_screenshot_texture, 0, D3D11_MAP_READ, 0, &map);
|
D3D::context->Map(s_screenshot_texture, 0, D3D11_MAP_READ, 0, &map);
|
||||||
|
|
||||||
DumpFrameData(reinterpret_cast<const u8*>(map.pData), source_width, source_height,
|
DumpFrameData(reinterpret_cast<const u8*>(map.pData), source_width, source_height, map.RowPitch,
|
||||||
map.RowPitch);
|
ticks);
|
||||||
FinishFrameData();
|
FinishFrameData();
|
||||||
|
|
||||||
D3D::context->Unmap(s_screenshot_texture, 0);
|
D3D::context->Unmap(s_screenshot_texture, 0);
|
||||||
|
|
|
@ -47,7 +47,7 @@ public:
|
||||||
TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) override;
|
TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) override;
|
||||||
|
|
||||||
void SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc,
|
void SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc,
|
||||||
float Gamma) override;
|
u64 ticks, float Gamma) override;
|
||||||
|
|
||||||
void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable,
|
void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable,
|
||||||
u32 color, u32 z) override;
|
u32 color, u32 z) override;
|
||||||
|
|
|
@ -632,7 +632,7 @@ void Renderer::SetBlendMode(bool force_update)
|
||||||
|
|
||||||
// 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::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height,
|
void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height,
|
||||||
const EFBRectangle& rc, float gamma)
|
const EFBRectangle& rc, u64 ticks, float gamma)
|
||||||
{
|
{
|
||||||
if ((!XFBWrited && !g_ActiveConfig.RealXFBEnabled()) || !fb_width || !fb_height)
|
if ((!XFBWrited && !g_ActiveConfig.RealXFBEnabled()) || !fb_width || !fb_height)
|
||||||
{
|
{
|
||||||
|
@ -778,7 +778,7 @@ void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height
|
||||||
CheckHR(s_screenshot_texture->Map(0, &read_range, &screenshot_texture_map));
|
CheckHR(s_screenshot_texture->Map(0, &read_range, &screenshot_texture_map));
|
||||||
|
|
||||||
DumpFrameData(reinterpret_cast<const u8*>(screenshot_texture_map), source_width, source_height,
|
DumpFrameData(reinterpret_cast<const u8*>(screenshot_texture_map), source_width, source_height,
|
||||||
dst_location.PlacedFootprint.Footprint.RowPitch);
|
dst_location.PlacedFootprint.Footprint.RowPitch, ticks);
|
||||||
FinishFrameData();
|
FinishFrameData();
|
||||||
|
|
||||||
D3D12_RANGE write_range = {};
|
D3D12_RANGE write_range = {};
|
||||||
|
|
|
@ -47,7 +47,7 @@ public:
|
||||||
TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) override;
|
TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) override;
|
||||||
|
|
||||||
void SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height, const EFBRectangle& rc,
|
void SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height, const EFBRectangle& rc,
|
||||||
float gamma) override;
|
u64 ticks, float gamma) override;
|
||||||
|
|
||||||
void ClearScreen(const EFBRectangle& rc, bool color_enable, bool alpha_enable, bool z_enable,
|
void ClearScreen(const EFBRectangle& rc, bool color_enable, bool alpha_enable, bool z_enable,
|
||||||
u32 color, u32 z) override;
|
u32 color, u32 z) override;
|
||||||
|
|
|
@ -38,7 +38,7 @@ TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::SwapImpl(u32, u32, u32, u32, const EFBRectangle&, float)
|
void Renderer::SwapImpl(u32, u32, u32, u32, const EFBRectangle&, u64, float)
|
||||||
{
|
{
|
||||||
UpdateActiveConfig();
|
UpdateActiveConfig();
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ public:
|
||||||
TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) override;
|
TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) override;
|
||||||
|
|
||||||
void SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height, const EFBRectangle& rc,
|
void SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height, const EFBRectangle& rc,
|
||||||
float gamma) override;
|
u64 ticks, float gamma) override;
|
||||||
|
|
||||||
void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable,
|
void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable,
|
||||||
u32 color, u32 z) override
|
u32 color, u32 z) override
|
||||||
|
|
|
@ -1339,7 +1339,7 @@ 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::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
|
void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
|
||||||
const EFBRectangle& rc, float Gamma)
|
const EFBRectangle& rc, u64 ticks, float Gamma)
|
||||||
{
|
{
|
||||||
if (g_ogl_config.bSupportsDebug)
|
if (g_ogl_config.bSupportsDebug)
|
||||||
{
|
{
|
||||||
|
@ -1452,7 +1452,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
|
||||||
flipped_trc.GetHeight(), GL_RGBA, GL_UNSIGNED_BYTE, image.data());
|
flipped_trc.GetHeight(), GL_RGBA, GL_UNSIGNED_BYTE, image.data());
|
||||||
|
|
||||||
DumpFrameData(image.data(), flipped_trc.GetWidth(), flipped_trc.GetHeight(),
|
DumpFrameData(image.data(), flipped_trc.GetWidth(), flipped_trc.GetHeight(),
|
||||||
flipped_trc.GetWidth() * 4, true);
|
flipped_trc.GetWidth() * 4, ticks, true);
|
||||||
FinishFrameData();
|
FinishFrameData();
|
||||||
}
|
}
|
||||||
// Finish up the current frame, print some stats
|
// Finish up the current frame, print some stats
|
||||||
|
|
|
@ -94,7 +94,7 @@ public:
|
||||||
TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) override;
|
TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) override;
|
||||||
|
|
||||||
void SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc,
|
void SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc,
|
||||||
float Gamma) override;
|
u64 ticks, float Gamma) override;
|
||||||
|
|
||||||
void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable,
|
void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable,
|
||||||
u32 color, u32 z) override;
|
u32 color, u32 z) override;
|
||||||
|
|
|
@ -110,7 +110,7 @@ void SWRenderer::UpdateColorTexture(EfbInterface::yuv422_packed* xfb, u32 fbWidt
|
||||||
|
|
||||||
// Called on the GPU thread
|
// Called on the GPU thread
|
||||||
void SWRenderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
|
void SWRenderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
|
||||||
const EFBRectangle& rc, float Gamma)
|
const EFBRectangle& rc, u64 ticks, float Gamma)
|
||||||
{
|
{
|
||||||
if (g_ActiveConfig.bUseXFB)
|
if (g_ActiveConfig.bUseXFB)
|
||||||
{
|
{
|
||||||
|
|
|
@ -34,7 +34,7 @@ public:
|
||||||
TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) override;
|
TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) override;
|
||||||
|
|
||||||
void SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc,
|
void SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc,
|
||||||
float Gamma) override;
|
u64 ticks, float Gamma) override;
|
||||||
|
|
||||||
void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable,
|
void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable,
|
||||||
u32 color, u32 z) override;
|
u32 color, u32 z) override;
|
||||||
|
|
|
@ -460,7 +460,7 @@ void Renderer::ReinterpretPixelData(unsigned int convtype)
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height,
|
void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height,
|
||||||
const EFBRectangle& rc, float gamma)
|
const EFBRectangle& rc, u64 ticks, float gamma)
|
||||||
{
|
{
|
||||||
// Flush any pending EFB pokes.
|
// Flush any pending EFB pokes.
|
||||||
m_framebuffer_mgr->FlushEFBPokes(m_state_tracker.get());
|
m_framebuffer_mgr->FlushEFBPokes(m_state_tracker.get());
|
||||||
|
@ -486,7 +486,7 @@ void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height
|
||||||
DumpFrameData(reinterpret_cast<const u8*>(m_screenshot_readback_texture->GetMapPointer()),
|
DumpFrameData(reinterpret_cast<const u8*>(m_screenshot_readback_texture->GetMapPointer()),
|
||||||
static_cast<int>(m_screenshot_render_texture->GetWidth()),
|
static_cast<int>(m_screenshot_render_texture->GetWidth()),
|
||||||
static_cast<int>(m_screenshot_render_texture->GetHeight()),
|
static_cast<int>(m_screenshot_render_texture->GetHeight()),
|
||||||
static_cast<int>(m_screenshot_readback_texture->GetRowStride()));
|
static_cast<int>(m_screenshot_readback_texture->GetRowStride()), ticks);
|
||||||
FinishFrameData();
|
FinishFrameData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ public:
|
||||||
TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) override;
|
TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) override;
|
||||||
|
|
||||||
void SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height, const EFBRectangle& rc,
|
void SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height, const EFBRectangle& rc,
|
||||||
float gamma) override;
|
u64 ticks, float gamma) override;
|
||||||
|
|
||||||
void ClearScreen(const EFBRectangle& rc, bool color_enable, bool alpha_enable, bool z_enable,
|
void ClearScreen(const EFBRectangle& rc, bool color_enable, bool alpha_enable, bool z_enable,
|
||||||
u32 color, u32 z) override;
|
u32 color, u32 z) override;
|
||||||
|
|
|
@ -20,7 +20,6 @@ extern "C" {
|
||||||
#include "Common/MsgHandler.h"
|
#include "Common/MsgHandler.h"
|
||||||
|
|
||||||
#include "Core/ConfigManager.h"
|
#include "Core/ConfigManager.h"
|
||||||
#include "Core/CoreTiming.h"
|
|
||||||
#include "Core/HW/SystemTimers.h"
|
#include "Core/HW/SystemTimers.h"
|
||||||
#include "Core/HW/VideoInterface.h" //for TargetRefreshRate
|
#include "Core/HW/VideoInterface.h" //for TargetRefreshRate
|
||||||
#include "Core/Movie.h"
|
#include "Core/Movie.h"
|
||||||
|
@ -41,6 +40,7 @@ static SwsContext* s_sws_context = nullptr;
|
||||||
static int s_width;
|
static int s_width;
|
||||||
static int s_height;
|
static int s_height;
|
||||||
static u64 s_last_frame;
|
static u64 s_last_frame;
|
||||||
|
static bool s_last_frame_is_valid = false;
|
||||||
static bool s_start_dumping = false;
|
static bool s_start_dumping = false;
|
||||||
static bool s_stop_dumping = false;
|
static bool s_stop_dumping = false;
|
||||||
static u64 s_last_pts;
|
static u64 s_last_pts;
|
||||||
|
@ -51,6 +51,7 @@ static const u8* s_stored_frame_data;
|
||||||
static int s_stored_frame_width;
|
static int s_stored_frame_width;
|
||||||
static int s_stored_frame_height;
|
static int s_stored_frame_height;
|
||||||
static int s_stored_frame_stride;
|
static int s_stored_frame_stride;
|
||||||
|
static u64 s_stored_frame_ticks;
|
||||||
|
|
||||||
static void InitAVCodec()
|
static void InitAVCodec()
|
||||||
{
|
{
|
||||||
|
@ -71,7 +72,7 @@ bool AVIDump::Start(int w, int h)
|
||||||
s_current_width = w;
|
s_current_width = w;
|
||||||
s_current_height = h;
|
s_current_height = h;
|
||||||
|
|
||||||
s_last_frame = CoreTiming::GetTicks();
|
s_last_frame_is_valid = false;
|
||||||
s_last_pts = 0;
|
s_last_pts = 0;
|
||||||
|
|
||||||
s_stop_dumping = false;
|
s_stop_dumping = false;
|
||||||
|
@ -169,14 +170,14 @@ static void PreparePacket(AVPacket* pkt)
|
||||||
pkt->size = 0;
|
pkt->size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AVIDump::AddFrame(const u8* data, int width, int height, int stride)
|
void AVIDump::AddFrame(const u8* data, int width, int height, int stride, u64 ticks)
|
||||||
{
|
{
|
||||||
// Store current frame data in case frame dumping stops before next frame update,
|
// Store current frame data in case frame dumping stops before next frame update,
|
||||||
// but make sure that you don't store the last stored frame and check the resolution upon
|
// but make sure that you don't store the last stored frame and check the resolution upon
|
||||||
// closing the file or else you store recursion, and dolphins don't like recursion.
|
// closing the file or else you store recursion, and dolphins don't like recursion.
|
||||||
if (!s_stop_dumping)
|
if (!s_stop_dumping)
|
||||||
{
|
{
|
||||||
StoreFrameData(data, width, height, stride);
|
StoreFrameData(data, width, height, stride, ticks);
|
||||||
CheckResolution(width, height);
|
CheckResolution(width, height);
|
||||||
}
|
}
|
||||||
s_src_frame->data[0] = const_cast<u8*>(data);
|
s_src_frame->data[0] = const_cast<u8*>(data);
|
||||||
|
@ -205,15 +206,20 @@ void AVIDump::AddFrame(const u8* data, int width, int height, int stride)
|
||||||
// Check to see if the first frame being dumped is the first frame of output from the emulator.
|
// Check to see if the first frame being dumped is the first frame of output from the emulator.
|
||||||
// This prevents an issue with starting dumping later in emulation from placing the frames
|
// This prevents an issue with starting dumping later in emulation from placing the frames
|
||||||
// incorrectly.
|
// incorrectly.
|
||||||
|
if (!s_last_frame_is_valid)
|
||||||
|
{
|
||||||
|
s_last_frame = ticks;
|
||||||
|
s_last_frame_is_valid = true;
|
||||||
|
}
|
||||||
if (!s_start_dumping && Movie::GetCurrentFrame() < 1)
|
if (!s_start_dumping && Movie::GetCurrentFrame() < 1)
|
||||||
{
|
{
|
||||||
delta = CoreTiming::GetTicks();
|
delta = ticks;
|
||||||
last_pts = AV_NOPTS_VALUE;
|
last_pts = AV_NOPTS_VALUE;
|
||||||
s_start_dumping = true;
|
s_start_dumping = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
delta = CoreTiming::GetTicks() - s_last_frame;
|
delta = ticks - s_last_frame;
|
||||||
last_pts = (s_last_pts * s_stream->codec->time_base.den) / SystemTimers::GetTicksPerSecond();
|
last_pts = (s_last_pts * s_stream->codec->time_base.den) / SystemTimers::GetTicksPerSecond();
|
||||||
}
|
}
|
||||||
u64 pts_in_ticks = s_last_pts + delta;
|
u64 pts_in_ticks = s_last_pts + delta;
|
||||||
|
@ -221,7 +227,7 @@ void AVIDump::AddFrame(const u8* data, int width, int height, int stride)
|
||||||
(pts_in_ticks * s_stream->codec->time_base.den) / SystemTimers::GetTicksPerSecond();
|
(pts_in_ticks * s_stream->codec->time_base.den) / SystemTimers::GetTicksPerSecond();
|
||||||
if (s_scaled_frame->pts != last_pts)
|
if (s_scaled_frame->pts != last_pts)
|
||||||
{
|
{
|
||||||
s_last_frame = CoreTiming::GetTicks();
|
s_last_frame = ticks;
|
||||||
s_last_pts = pts_in_ticks;
|
s_last_pts = pts_in_ticks;
|
||||||
error = avcodec_encode_video2(s_stream->codec, &pkt, s_scaled_frame, &got_packet);
|
error = avcodec_encode_video2(s_stream->codec, &pkt, s_scaled_frame, &got_packet);
|
||||||
}
|
}
|
||||||
|
@ -255,7 +261,8 @@ void AVIDump::Stop()
|
||||||
{
|
{
|
||||||
s_stop_dumping = true;
|
s_stop_dumping = true;
|
||||||
// Write the last stored frame just in case frame dumping stops before the next frame update
|
// Write the last stored frame just in case frame dumping stops before the next frame update
|
||||||
AddFrame(s_stored_frame_data, s_stored_frame_width, s_stored_frame_height, s_stored_frame_stride);
|
AddFrame(s_stored_frame_data, s_stored_frame_width, s_stored_frame_height, s_stored_frame_stride,
|
||||||
|
s_stored_frame_ticks);
|
||||||
av_write_trailer(s_format_context);
|
av_write_trailer(s_format_context);
|
||||||
CloseFile();
|
CloseFile();
|
||||||
s_file_index = 0;
|
s_file_index = 0;
|
||||||
|
@ -295,7 +302,7 @@ void AVIDump::CloseFile()
|
||||||
|
|
||||||
void AVIDump::DoState()
|
void AVIDump::DoState()
|
||||||
{
|
{
|
||||||
s_last_frame = CoreTiming::GetTicks();
|
s_last_frame_is_valid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AVIDump::CheckResolution(int width, int height)
|
void AVIDump::CheckResolution(int width, int height)
|
||||||
|
@ -316,10 +323,11 @@ void AVIDump::CheckResolution(int width, int height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AVIDump::StoreFrameData(const u8* data, int width, int height, int stride)
|
void AVIDump::StoreFrameData(const u8* data, int width, int height, int stride, u64 ticks)
|
||||||
{
|
{
|
||||||
s_stored_frame_data = data;
|
s_stored_frame_data = data;
|
||||||
s_stored_frame_width = width;
|
s_stored_frame_width = width;
|
||||||
s_stored_frame_height = height;
|
s_stored_frame_height = height;
|
||||||
s_stored_frame_stride = stride;
|
s_stored_frame_stride = stride;
|
||||||
|
s_stored_frame_ticks = ticks;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,11 +12,11 @@ private:
|
||||||
static bool CreateFile();
|
static bool CreateFile();
|
||||||
static void CloseFile();
|
static void CloseFile();
|
||||||
static void CheckResolution(int width, int height);
|
static void CheckResolution(int width, int height);
|
||||||
static void StoreFrameData(const u8* data, int width, int height, int stride);
|
static void StoreFrameData(const u8* data, int width, int height, int stride, u64 ticks);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static bool Start(int w, int h);
|
static bool Start(int w, int h);
|
||||||
static void AddFrame(const u8* data, int width, int height, int stride);
|
static void AddFrame(const u8* data, int width, int height, int stride, u64 ticks);
|
||||||
static void Stop();
|
static void Stop();
|
||||||
static void DoState();
|
static void DoState();
|
||||||
};
|
};
|
||||||
|
|
|
@ -135,7 +135,7 @@ void AsyncRequests::HandleEvent(const AsyncRequests::Event& e)
|
||||||
|
|
||||||
case Event::SWAP_EVENT:
|
case Event::SWAP_EVENT:
|
||||||
Renderer::Swap(e.swap_event.xfbAddr, e.swap_event.fbWidth, e.swap_event.fbStride,
|
Renderer::Swap(e.swap_event.xfbAddr, e.swap_event.fbWidth, e.swap_event.fbStride,
|
||||||
e.swap_event.fbHeight, rc);
|
e.swap_event.fbHeight, rc, e.time);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Event::BBOX_READ:
|
case Event::BBOX_READ:
|
||||||
|
|
|
@ -47,14 +47,15 @@ void VideoBackendBase::Video_ExitLoop()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run from the CPU thread (from VideoInterface.cpp)
|
// Run from the CPU thread (from VideoInterface.cpp)
|
||||||
void VideoBackendBase::Video_BeginField(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight)
|
void VideoBackendBase::Video_BeginField(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
|
||||||
|
u64 ticks)
|
||||||
{
|
{
|
||||||
if (m_initialized && g_ActiveConfig.bUseXFB && g_renderer)
|
if (m_initialized && g_ActiveConfig.bUseXFB && g_renderer)
|
||||||
{
|
{
|
||||||
Fifo::SyncGPU(Fifo::SyncGPUReason::Swap);
|
Fifo::SyncGPU(Fifo::SyncGPUReason::Swap);
|
||||||
|
|
||||||
AsyncRequests::Event e;
|
AsyncRequests::Event e;
|
||||||
e.time = 0;
|
e.time = ticks;
|
||||||
e.type = AsyncRequests::Event::SWAP_EVENT;
|
e.type = AsyncRequests::Event::SWAP_EVENT;
|
||||||
|
|
||||||
e.swap_event.xfbAddr = xfbAddr;
|
e.swap_event.xfbAddr = xfbAddr;
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
#include "Core/ConfigManager.h"
|
#include "Core/ConfigManager.h"
|
||||||
#include "Core/Core.h"
|
#include "Core/Core.h"
|
||||||
|
#include "Core/CoreTiming.h"
|
||||||
#include "Core/FifoPlayer/FifoRecorder.h"
|
#include "Core/FifoPlayer/FifoRecorder.h"
|
||||||
#include "Core/HW/VideoInterface.h"
|
#include "Core/HW/VideoInterface.h"
|
||||||
#include "Core/Host.h"
|
#include "Core/Host.h"
|
||||||
|
@ -138,8 +139,11 @@ void Renderer::RenderToXFB(u32 xfbAddr, const EFBRectangle& sourceRc, u32 fbStri
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// The timing is not predictable here. So try to use the XFB path to dump frames.
|
||||||
|
u64 ticks = CoreTiming::GetTicks();
|
||||||
|
|
||||||
// below div two to convert from bytes to pixels - it expects width, not stride
|
// below div two to convert from bytes to pixels - it expects width, not stride
|
||||||
Swap(xfbAddr, fbStride / 2, fbStride / 2, fbHeight, sourceRc, Gamma);
|
Swap(xfbAddr, fbStride / 2, fbStride / 2, fbHeight, sourceRc, ticks, Gamma);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -516,10 +520,10 @@ void Renderer::RecordVideoMemory()
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc,
|
void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc,
|
||||||
float Gamma)
|
u64 ticks, float Gamma)
|
||||||
{
|
{
|
||||||
// TODO: merge more generic parts into VideoCommon
|
// TODO: merge more generic parts into VideoCommon
|
||||||
g_renderer->SwapImpl(xfbAddr, fbWidth, fbStride, fbHeight, rc, Gamma);
|
g_renderer->SwapImpl(xfbAddr, fbWidth, fbStride, fbHeight, rc, ticks, Gamma);
|
||||||
|
|
||||||
if (XFBWrited)
|
if (XFBWrited)
|
||||||
g_renderer->m_fps_counter.Update();
|
g_renderer->m_fps_counter.Update();
|
||||||
|
@ -558,7 +562,8 @@ bool Renderer::IsFrameDumping()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::DumpFrameData(const u8* data, int w, int h, int stride, bool swap_upside_down)
|
void Renderer::DumpFrameData(const u8* data, int w, int h, int stride, u64 ticks,
|
||||||
|
bool swap_upside_down)
|
||||||
{
|
{
|
||||||
if (w == 0 || h == 0)
|
if (w == 0 || h == 0)
|
||||||
return;
|
return;
|
||||||
|
@ -601,7 +606,7 @@ void Renderer::DumpFrameData(const u8* data, int w, int h, int stride, bool swap
|
||||||
}
|
}
|
||||||
if (m_AVI_dumping)
|
if (m_AVI_dumping)
|
||||||
{
|
{
|
||||||
AVIDump::AddFrame(m_frame_data.data(), w, h, stride);
|
AVIDump::AddFrame(m_frame_data.data(), w, h, stride, ticks);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_last_frame_dumped = true;
|
m_last_frame_dumped = true;
|
||||||
|
|
|
@ -123,9 +123,9 @@ public:
|
||||||
|
|
||||||
// Finish up the current frame, print some stats
|
// Finish up the current frame, print some stats
|
||||||
static void Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc,
|
static void Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc,
|
||||||
float Gamma = 1.0f);
|
u64 ticks, float Gamma = 1.0f);
|
||||||
virtual void SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
|
virtual void SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
|
||||||
const EFBRectangle& rc, float Gamma = 1.0f) = 0;
|
const EFBRectangle& rc, u64 ticks, float Gamma = 1.0f) = 0;
|
||||||
|
|
||||||
static PEControl::PixelFormat GetPrevPixelFormat() { return prev_efb_format; }
|
static PEControl::PixelFormat GetPrevPixelFormat() { return prev_efb_format; }
|
||||||
static void StorePixelFormat(PEControl::PixelFormat new_format) { prev_efb_format = new_format; }
|
static void StorePixelFormat(PEControl::PixelFormat new_format) { prev_efb_format = new_format; }
|
||||||
|
@ -146,7 +146,8 @@ protected:
|
||||||
static void RecordVideoMemory();
|
static void RecordVideoMemory();
|
||||||
|
|
||||||
bool IsFrameDumping();
|
bool IsFrameDumping();
|
||||||
void DumpFrameData(const u8* data, int w, int h, int stride, bool swap_upside_down = false);
|
void DumpFrameData(const u8* data, int w, int h, int stride, u64 ticks,
|
||||||
|
bool swap_upside_down = false);
|
||||||
void FinishFrameData();
|
void FinishFrameData();
|
||||||
|
|
||||||
static volatile bool s_bScreenshot;
|
static volatile bool s_bScreenshot;
|
||||||
|
|
|
@ -75,7 +75,7 @@ public:
|
||||||
void Video_ExitLoop();
|
void Video_ExitLoop();
|
||||||
virtual void Video_Cleanup() = 0; // called from gl/d3d thread
|
virtual void Video_Cleanup() = 0; // called from gl/d3d thread
|
||||||
|
|
||||||
void Video_BeginField(u32, u32, u32, u32);
|
void Video_BeginField(u32, u32, u32, u32, u64);
|
||||||
|
|
||||||
u32 Video_AccessEFB(EFBAccessType, u32, u32, u32);
|
u32 Video_AccessEFB(EFBAccessType, u32, u32, u32);
|
||||||
u32 Video_GetQueryResult(PerfQueryType type);
|
u32 Video_GetQueryResult(PerfQueryType type);
|
||||||
|
|
Loading…
Reference in New Issue