mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
Merge pull request #1035 from GiuseppeGorgoglione/master
Direct3D HLSL: use aviwrite to record avi movies [GiuseppeGorgoglione]
This commit is contained in:
commit
d68203e283
@ -147,7 +147,6 @@ const options_entry osd_options::s_option_entries[] =
|
||||
{ OSDOPTION_BGFX_DEBUG, "0", OPTION_BOOLEAN, "enable BGFX debugging statistics" },
|
||||
{ OSDOPTION_BGFX_SCREEN_CHAINS, "default", OPTION_STRING, "comma-delimited list of screen chain JSON names, colon-delimited per-window" },
|
||||
{ OSDOPTION_BGFX_SHADOW_MASK, "slot-mask.png", OPTION_STRING, "shadow mask texture name" },
|
||||
{ OSDOPTION_BGFX_AVI_NAME, "bgfx.avi", OPTION_STRING, "filename for BGFX output logging" },
|
||||
|
||||
// End of list
|
||||
{ nullptr }
|
||||
|
@ -83,7 +83,6 @@
|
||||
#define OSDOPTION_BGFX_DEBUG "bgfx_debug"
|
||||
#define OSDOPTION_BGFX_SCREEN_CHAINS "bgfx_screen_chains"
|
||||
#define OSDOPTION_BGFX_SHADOW_MASK "bgfx_shadow_mask"
|
||||
#define OSDOPTION_BGFX_AVI_NAME "bgfx_avi_name"
|
||||
|
||||
//============================================================
|
||||
// TYPE DEFINITIONS
|
||||
@ -157,7 +156,6 @@ public:
|
||||
bool bgfx_debug() const { return bool_value(OSDOPTION_BGFX_DEBUG); }
|
||||
const char *bgfx_screen_chains() const { return value(OSDOPTION_BGFX_SCREEN_CHAINS); }
|
||||
const char *bgfx_shadow_mask() const { return value(OSDOPTION_BGFX_SHADOW_MASK); }
|
||||
const char *bgfx_avi_name() const { return value(OSDOPTION_BGFX_AVI_NAME); }
|
||||
|
||||
private:
|
||||
static const options_entry s_option_entries[];
|
||||
|
@ -27,17 +27,14 @@ avi_write::~avi_write()
|
||||
}
|
||||
}
|
||||
|
||||
void avi_write::record(std::string name)
|
||||
void avi_write::record()
|
||||
{
|
||||
if (m_recording)
|
||||
{
|
||||
end_avi_recording();
|
||||
}
|
||||
|
||||
if (name != "")
|
||||
{
|
||||
begin_avi_recording(name);
|
||||
}
|
||||
begin_avi_recording();
|
||||
}
|
||||
|
||||
void avi_write::stop()
|
||||
@ -46,7 +43,7 @@ void avi_write::stop()
|
||||
end_avi_recording();
|
||||
}
|
||||
|
||||
void avi_write::begin_avi_recording(std::string name)
|
||||
void avi_write::begin_avi_recording()
|
||||
{
|
||||
// stop any existing recording
|
||||
end_avi_recording();
|
||||
@ -73,25 +70,20 @@ void avi_write::begin_avi_recording(std::string name)
|
||||
info.audio_samplebits = 16;
|
||||
info.audio_samplerate = m_machine.sample_rate();
|
||||
|
||||
// compute the frame time
|
||||
m_frame_period = attotime::from_seconds(1000) / info.video_timescale;
|
||||
|
||||
// create a new temporary movie file
|
||||
osd_file::error filerr;
|
||||
std::string fullpath;
|
||||
{
|
||||
emu_file tempfile(m_machine.options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
|
||||
filerr = tempfile.open(name.c_str());
|
||||
|
||||
// compute the frame time
|
||||
m_frame_period = attotime::from_seconds(1000) / info.video_timescale;
|
||||
|
||||
// if we succeeded, make a copy of the name and create the real file over top
|
||||
if (filerr == osd_file::error::NONE)
|
||||
{
|
||||
fullpath = tempfile.fullpath();
|
||||
}
|
||||
}
|
||||
emu_file tempfile(m_machine.options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
|
||||
|
||||
osd_file::error filerr = m_machine.video().open_next(tempfile, "avi");
|
||||
|
||||
// if we succeeded, make a copy of the name and create the real file over top
|
||||
if (filerr == osd_file::error::NONE)
|
||||
{
|
||||
std::string fullpath = tempfile.fullpath();
|
||||
tempfile.close();
|
||||
|
||||
// create the file and free the string
|
||||
avi_file::error avierr = avi_file::create(fullpath, info, m_output_file);
|
||||
if (avierr != avi_file::error::NONE)
|
||||
|
@ -22,7 +22,7 @@ public:
|
||||
avi_write(running_machine& machine, uint32_t width, uint32_t height);
|
||||
~avi_write();
|
||||
|
||||
void record(std::string name);
|
||||
void record();
|
||||
void stop();
|
||||
void audio_frame(const INT16 *buffer, int samples_this_frame);
|
||||
void video_frame(bitmap_rgb32& snap);
|
||||
@ -31,7 +31,7 @@ public:
|
||||
bool recording() const { return m_recording; }
|
||||
|
||||
private:
|
||||
void begin_avi_recording(std::string name);
|
||||
void begin_avi_recording();
|
||||
void end_avi_recording();
|
||||
|
||||
running_machine& m_machine;
|
||||
|
@ -19,6 +19,7 @@
|
||||
// MAMEOS headers
|
||||
#include "winmain.h"
|
||||
#include "window.h"
|
||||
#include "modules/render/aviwrite.h"
|
||||
#include "modules/render/drawd3d.h"
|
||||
#include "d3dcomm.h"
|
||||
#include "strconv.h"
|
||||
@ -26,11 +27,6 @@
|
||||
#include "../frontend/mame/ui/slider.h"
|
||||
|
||||
|
||||
//============================================================
|
||||
// GLOBALS
|
||||
//============================================================
|
||||
|
||||
|
||||
//============================================================
|
||||
// PROTOTYPES
|
||||
//============================================================
|
||||
@ -38,17 +34,134 @@
|
||||
static void get_vector(const char *data, int count, float *out, bool report_error);
|
||||
|
||||
|
||||
//============================================================
|
||||
// HLSL post-render AVI recorder
|
||||
//============================================================
|
||||
|
||||
class movie_recorder
|
||||
{
|
||||
public:
|
||||
movie_recorder(running_machine& machine, renderer_d3d9 *d3d, int width, int height)
|
||||
: m_initialized(false), m_d3d(d3d), m_width(width), m_height(height)
|
||||
, m_sys_texture(nullptr), m_sys_surface(nullptr)
|
||||
, m_vid_texture(nullptr), m_vid_surface(nullptr)
|
||||
{
|
||||
HRESULT result;
|
||||
|
||||
m_avi_writer = std::make_unique<avi_write>(machine, width, height);
|
||||
|
||||
m_frame.allocate(width, height);
|
||||
if (!m_frame.valid())
|
||||
return;
|
||||
|
||||
result = d3d->get_device()->CreateTexture(width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &m_sys_texture, nullptr);
|
||||
if (FAILED(result))
|
||||
{
|
||||
osd_printf_verbose("Direct3D: Unable to init system-memory target for HLSL AVI dumping (%08lX)\n", result);
|
||||
return;
|
||||
}
|
||||
m_sys_texture->GetSurfaceLevel(0, &m_sys_surface);
|
||||
|
||||
result = d3d->get_device()->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_vid_texture, nullptr);
|
||||
if (FAILED(result))
|
||||
{
|
||||
osd_printf_verbose("Direct3D: Unable to init video-memory target for HLSL AVI dumping (%08lX)\n", result);
|
||||
return;
|
||||
}
|
||||
m_vid_texture->GetSurfaceLevel(0, &m_vid_surface);
|
||||
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
~movie_recorder()
|
||||
{
|
||||
if (m_sys_texture != nullptr)
|
||||
m_sys_texture->Release();
|
||||
|
||||
if (m_sys_surface != nullptr)
|
||||
m_sys_surface->Release();
|
||||
|
||||
if (m_vid_texture != nullptr)
|
||||
m_vid_texture->Release();
|
||||
|
||||
if (m_vid_surface != nullptr)
|
||||
m_vid_surface->Release();
|
||||
}
|
||||
|
||||
void record()
|
||||
{
|
||||
if (!m_initialized)
|
||||
return;
|
||||
|
||||
m_avi_writer->record();
|
||||
}
|
||||
|
||||
void save_frame()
|
||||
{
|
||||
if (!m_initialized)
|
||||
return;
|
||||
|
||||
// copy the frame from video memory, where it is not accessible, to system memory
|
||||
HRESULT result = m_d3d->get_device()->GetRenderTargetData(m_vid_surface, m_sys_surface);
|
||||
if (FAILED(result))
|
||||
return;
|
||||
|
||||
D3DLOCKED_RECT rect;
|
||||
result = m_sys_surface->LockRect(&rect, nullptr, D3DLOCK_DISCARD);
|
||||
if (FAILED(result))
|
||||
return;
|
||||
|
||||
for (int y = 0; y < m_height; y++)
|
||||
{
|
||||
DWORD *src = (DWORD *)((BYTE *)rect.pBits + y * rect.Pitch);
|
||||
UINT32 *dst = &m_frame.pix32(y);
|
||||
|
||||
for (int x = 0; x < m_width; x++)
|
||||
{
|
||||
*dst++ = *src++;
|
||||
}
|
||||
}
|
||||
|
||||
result = m_sys_surface->UnlockRect();
|
||||
if (FAILED(result))
|
||||
osd_printf_verbose("Direct3D: Error %08lX during texture UnlockRect call\n", result);
|
||||
|
||||
m_avi_writer->video_frame(m_frame);
|
||||
}
|
||||
|
||||
IDirect3DSurface9 * target_surface() { return m_vid_surface; }
|
||||
|
||||
private:
|
||||
bool m_initialized;
|
||||
|
||||
renderer_d3d9 * m_d3d;
|
||||
|
||||
std::unique_ptr<avi_write> m_avi_writer;
|
||||
|
||||
bitmap_rgb32 m_frame;
|
||||
int m_width;
|
||||
int m_height;
|
||||
IDirect3DTexture9 * m_sys_texture; // texture in system memory
|
||||
IDirect3DSurface9 * m_sys_surface; // surface in system memory
|
||||
IDirect3DTexture9 * m_vid_texture; // texture in video memory
|
||||
IDirect3DSurface9 * m_vid_surface; // surface in video memory
|
||||
};
|
||||
|
||||
|
||||
//============================================================
|
||||
// shader manager constructor
|
||||
//============================================================
|
||||
|
||||
shaders::shaders() :
|
||||
d3dintf(nullptr), machine(nullptr), d3d(nullptr), post_fx_enable(false), oversampling_enable(false), num_screens(0), curr_screen(0),
|
||||
shadow_texture(nullptr), options(nullptr), avi_output_file(nullptr), avi_frame(0), avi_copy_surface(nullptr), avi_copy_texture(nullptr), avi_final_target(nullptr), avi_final_texture(nullptr),
|
||||
black_surface(nullptr), black_texture(nullptr), render_snap(false), snap_rendered(false), snap_copy_target(nullptr), snap_copy_texture(nullptr), snap_target(nullptr), snap_texture(nullptr),
|
||||
snap_width(0), snap_height(0), initialized(false), backbuffer(nullptr), curr_effect(nullptr), default_effect(nullptr), prescale_effect(nullptr), post_effect(nullptr),
|
||||
distortion_effect(nullptr), focus_effect(nullptr), phosphor_effect(nullptr), deconverge_effect(nullptr), color_effect(nullptr), ntsc_effect(nullptr), bloom_effect(nullptr),
|
||||
downsample_effect(nullptr), vector_effect(nullptr), curr_texture(nullptr), curr_render_target(nullptr), curr_poly(nullptr)
|
||||
d3dintf(nullptr), machine(nullptr), d3d(nullptr), post_fx_enable(false), oversampling_enable(false),
|
||||
num_screens(0), curr_screen(0), shadow_texture(nullptr), options(nullptr), black_surface(nullptr),
|
||||
black_texture(nullptr), recording_movie(false),render_snap(false), snap_copy_target(nullptr),
|
||||
snap_copy_texture(nullptr), snap_target(nullptr), snap_texture(nullptr), snap_width(0), snap_height(0),
|
||||
initialized(false), backbuffer(nullptr), curr_effect(nullptr), default_effect(nullptr),
|
||||
prescale_effect(nullptr), post_effect(nullptr), distortion_effect(nullptr), focus_effect(nullptr),
|
||||
phosphor_effect(nullptr), deconverge_effect(nullptr), color_effect(nullptr), ntsc_effect(nullptr),
|
||||
bloom_effect(nullptr), downsample_effect(nullptr), vector_effect(nullptr), curr_texture(nullptr),
|
||||
curr_render_target(nullptr), curr_poly(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
@ -73,15 +186,13 @@ shaders::~shaders()
|
||||
|
||||
|
||||
//============================================================
|
||||
// shaders::window_save
|
||||
// shaders::save_snapshot
|
||||
//============================================================
|
||||
|
||||
void shaders::window_save()
|
||||
void shaders::save_snapshot()
|
||||
{
|
||||
if (!enabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
HRESULT result = d3d->get_device()->CreateTexture(snap_width, snap_height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &snap_copy_texture, nullptr);
|
||||
if (FAILED(result))
|
||||
@ -100,88 +211,31 @@ void shaders::window_save()
|
||||
snap_texture->GetSurfaceLevel(0, &snap_target);
|
||||
|
||||
render_snap = true;
|
||||
snap_rendered = false;
|
||||
}
|
||||
|
||||
|
||||
//============================================================
|
||||
// shaders::window_record
|
||||
// shaders::record_movie
|
||||
//============================================================
|
||||
|
||||
void shaders::window_record()
|
||||
void shaders::record_movie()
|
||||
{
|
||||
if (!enabled())
|
||||
return;
|
||||
|
||||
if (recording_movie)
|
||||
{
|
||||
recorder.reset();
|
||||
recording_movie = false;
|
||||
return;
|
||||
}
|
||||
|
||||
windows_options &options = downcast<windows_options &>(machine->options());
|
||||
const char *filename = options.d3d_hlsl_write();
|
||||
|
||||
if (avi_output_file != nullptr)
|
||||
{
|
||||
end_avi_recording();
|
||||
}
|
||||
else if (filename[0] != 0)
|
||||
{
|
||||
begin_avi_recording(filename);
|
||||
}
|
||||
recorder = std::make_unique<movie_recorder>(*machine, d3d, snap_width, snap_height);
|
||||
recorder->record();
|
||||
recording_movie = true;
|
||||
}
|
||||
|
||||
|
||||
//============================================================
|
||||
// shaders::avi_update_snap
|
||||
//============================================================
|
||||
|
||||
void shaders::avi_update_snap(IDirect3DSurface9 *surface)
|
||||
{
|
||||
if (!enabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
D3DLOCKED_RECT rect;
|
||||
|
||||
// if we don't have a bitmap, or if it's not the right size, allocate a new one
|
||||
if (!avi_snap.valid() || snap_width != avi_snap.width() || snap_height != avi_snap.height())
|
||||
{
|
||||
avi_snap.allocate(snap_width, snap_height);
|
||||
}
|
||||
|
||||
// copy the texture
|
||||
HRESULT result = d3d->get_device()->GetRenderTargetData(surface, avi_copy_surface);
|
||||
if (FAILED(result))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// lock the texture
|
||||
result = avi_copy_surface->LockRect(&rect, nullptr, D3DLOCK_DISCARD);
|
||||
if (FAILED(result))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// loop over Y
|
||||
for (int srcy = 0; srcy < snap_height; srcy++)
|
||||
{
|
||||
DWORD *src = (DWORD *)((BYTE *)rect.pBits + srcy * rect.Pitch);
|
||||
UINT32 *dst = &avi_snap.pix32(srcy);
|
||||
|
||||
for (int x = 0; x < snap_width; x++)
|
||||
{
|
||||
*dst++ = *src++;
|
||||
}
|
||||
}
|
||||
|
||||
// unlock
|
||||
result = avi_copy_surface->UnlockRect();
|
||||
if (FAILED(result))
|
||||
osd_printf_verbose("Direct3D: Error %08lX during texture UnlockRect call\n", result);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//============================================================
|
||||
// hlsl_render_snapshot
|
||||
//============================================================
|
||||
@ -189,39 +243,26 @@ void shaders::avi_update_snap(IDirect3DSurface9 *surface)
|
||||
void shaders::render_snapshot(IDirect3DSurface9 *surface)
|
||||
{
|
||||
if (!enabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
D3DLOCKED_RECT rect;
|
||||
|
||||
render_snap = false;
|
||||
|
||||
// if we don't have a bitmap, or if it's not the right size, allocate a new one
|
||||
if (!avi_snap.valid() || snap_width != avi_snap.width() || snap_height != avi_snap.height())
|
||||
{
|
||||
avi_snap.allocate(snap_width, snap_height);
|
||||
}
|
||||
bitmap_rgb32 snapshot(snap_width, snap_height);
|
||||
if (!snapshot.valid())
|
||||
return;
|
||||
|
||||
// copy the texture
|
||||
HRESULT result = d3d->get_device()->GetRenderTargetData(surface, snap_copy_target);
|
||||
if (FAILED(result))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// lock the texture
|
||||
D3DLOCKED_RECT rect;
|
||||
result = snap_copy_target->LockRect(&rect, nullptr, D3DLOCK_DISCARD);
|
||||
if (FAILED(result))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// loop over Y
|
||||
for (int srcy = 0; srcy < snap_height; srcy++)
|
||||
for (int y = 0; y < snap_height; y++)
|
||||
{
|
||||
DWORD *src = (DWORD *)((BYTE *)rect.pBits + srcy * rect.Pitch);
|
||||
UINT32 *dst = &avi_snap.pix32(srcy);
|
||||
DWORD *src = (DWORD *)((BYTE *)rect.pBits + y * rect.Pitch);
|
||||
UINT32 *dst = &snapshot.pix32(y);
|
||||
|
||||
for (int x = 0; x < snap_width; x++)
|
||||
{
|
||||
@ -232,9 +273,7 @@ void shaders::render_snapshot(IDirect3DSurface9 *surface)
|
||||
emu_file file(machine->options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
|
||||
osd_file::error filerr = machine->video().open_next(file, "png");
|
||||
if (filerr != osd_file::error::NONE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// add two text entries describing the image
|
||||
std::string text1 = std::string(emulator_info::get_appname()).append(" ").append(emulator_info::get_build_version());
|
||||
@ -244,16 +283,13 @@ void shaders::render_snapshot(IDirect3DSurface9 *surface)
|
||||
png_add_text(&pnginfo, "System", text2.c_str());
|
||||
|
||||
// now do the actual work
|
||||
png_error error = png_write_bitmap(file, &pnginfo, avi_snap, 1 << 24, nullptr);
|
||||
png_error error = png_write_bitmap(file, &pnginfo, snapshot, 1 << 24, nullptr);
|
||||
if (error != PNGERR_NONE)
|
||||
{
|
||||
osd_printf_error("Error generating PNG for HLSL snapshot: png_error = %d\n", error);
|
||||
}
|
||||
|
||||
// free any data allocated
|
||||
png_free(&pnginfo);
|
||||
|
||||
// unlock
|
||||
result = snap_copy_target->UnlockRect();
|
||||
if (FAILED(result))
|
||||
osd_printf_verbose("Direct3D: Error %08lX during texture UnlockRect call\n", result);
|
||||
@ -284,141 +320,6 @@ void shaders::render_snapshot(IDirect3DSurface9 *surface)
|
||||
}
|
||||
|
||||
|
||||
//============================================================
|
||||
// shaders::record_texture
|
||||
//============================================================
|
||||
|
||||
void shaders::record_texture()
|
||||
{
|
||||
if (!enabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IDirect3DSurface9 *surface = avi_final_target;
|
||||
|
||||
// ignore if nothing to do
|
||||
if (avi_output_file == nullptr || surface == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// get the current time
|
||||
attotime curtime = machine->time();
|
||||
|
||||
avi_update_snap(surface);
|
||||
|
||||
// loop until we hit the right time
|
||||
while (avi_next_frame_time <= curtime)
|
||||
{
|
||||
// handle an AVI recording
|
||||
// write the next frame
|
||||
avi_file::error avierr = avi_output_file->append_video_frame(avi_snap);
|
||||
if (avierr != avi_file::error::NONE)
|
||||
{
|
||||
end_avi_recording();
|
||||
return;
|
||||
}
|
||||
|
||||
// advance time
|
||||
avi_next_frame_time += avi_frame_period;
|
||||
avi_frame++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================
|
||||
// shaders::end_avi_recording
|
||||
//============================================================
|
||||
|
||||
void shaders::end_avi_recording()
|
||||
{
|
||||
if (!enabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (avi_output_file)
|
||||
{
|
||||
avi_output_file.reset();
|
||||
}
|
||||
|
||||
avi_output_file = nullptr;
|
||||
avi_frame = 0;
|
||||
}
|
||||
|
||||
|
||||
//============================================================
|
||||
// shaders::begin_avi_recording
|
||||
//============================================================
|
||||
|
||||
void shaders::begin_avi_recording(const char *name)
|
||||
{
|
||||
if (!enabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// stop any existing recording
|
||||
end_avi_recording();
|
||||
|
||||
// reset the state
|
||||
avi_frame = 0;
|
||||
avi_next_frame_time = machine->time();
|
||||
|
||||
// build up information about this new movie
|
||||
avi_file::movie_info info;
|
||||
info.video_format = 0;
|
||||
info.video_timescale = 1000 * ((machine->first_screen() != nullptr) ? ATTOSECONDS_TO_HZ(machine->first_screen()->frame_period().m_attoseconds) : screen_device::DEFAULT_FRAME_RATE);
|
||||
info.video_sampletime = 1000;
|
||||
info.video_numsamples = 0;
|
||||
info.video_width = snap_width;
|
||||
info.video_height = snap_height;
|
||||
info.video_depth = 24;
|
||||
|
||||
info.audio_format = 0;
|
||||
info.audio_timescale = machine->sample_rate();
|
||||
info.audio_sampletime = 1;
|
||||
info.audio_numsamples = 0;
|
||||
info.audio_channels = 2;
|
||||
info.audio_samplebits = 16;
|
||||
info.audio_samplerate = machine->sample_rate();
|
||||
|
||||
// create a new temporary movie file
|
||||
osd_file::error filerr;
|
||||
std::string fullpath;
|
||||
|
||||
emu_file tempfile(machine->options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
|
||||
if (name != nullptr)
|
||||
{
|
||||
filerr = tempfile.open(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
filerr = machine->video().open_next(tempfile, "avi");
|
||||
}
|
||||
|
||||
// compute the frame time
|
||||
avi_frame_period = attotime::from_seconds(1000) / info.video_timescale;
|
||||
|
||||
// if we succeeded, make a copy of the name and create the real file over top
|
||||
if (filerr == osd_file::error::NONE)
|
||||
{
|
||||
fullpath = tempfile.fullpath();
|
||||
}
|
||||
|
||||
if (filerr == osd_file::error::NONE)
|
||||
{
|
||||
// create the file and free the string
|
||||
avi_file::error avierr = avi_file::create(fullpath, info, avi_output_file);
|
||||
if (avierr != avi_file::error::NONE)
|
||||
{
|
||||
osd_printf_error("Error creating AVI: %s\n", avi_file::error_string(avierr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================
|
||||
// remove_cache_target - remove an active cache target
|
||||
//============================================================
|
||||
@ -757,29 +658,15 @@ int shaders::create_resources()
|
||||
result = d3d->get_device()->SetRenderTarget(0, black_surface);
|
||||
if (FAILED(result))
|
||||
osd_printf_verbose("Direct3D: Error %08lX during device SetRenderTarget call\n", result);
|
||||
|
||||
result = d3d->get_device()->Clear(0, nullptr, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0);
|
||||
if (FAILED(result))
|
||||
osd_printf_verbose("Direct3D: Error %08lX during device clear call\n", result);
|
||||
|
||||
result = d3d->get_device()->SetRenderTarget(0, backbuffer);
|
||||
if (FAILED(result))
|
||||
osd_printf_verbose("Direct3D: Error %08lX during device SetRenderTarget call\n", result);
|
||||
|
||||
result = d3d->get_device()->CreateTexture(snap_width, snap_height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &avi_copy_texture, nullptr);
|
||||
if (FAILED(result))
|
||||
{
|
||||
osd_printf_verbose("Direct3D: Unable to init system-memory target for HLSL AVI dumping (%08lX)\n", result);
|
||||
return 1;
|
||||
}
|
||||
avi_copy_texture->GetSurfaceLevel(0, &avi_copy_surface);
|
||||
|
||||
result = d3d->get_device()->CreateTexture(snap_width, snap_height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &avi_final_texture, nullptr);
|
||||
if (FAILED(result))
|
||||
{
|
||||
osd_printf_verbose("Direct3D: Unable to init video-memory target for HLSL AVI dumping (%08lX)\n", result);
|
||||
return 1;
|
||||
}
|
||||
avi_final_texture->GetSurfaceLevel(0, &avi_final_target);
|
||||
|
||||
emu_file file(machine->options().art_path(), OPEN_FLAG_READ);
|
||||
render_load_png(shadow_bitmap, file, nullptr, options->shadow_mask_texture);
|
||||
|
||||
@ -947,16 +834,6 @@ void shaders::begin_draw()
|
||||
}
|
||||
|
||||
|
||||
//============================================================
|
||||
// shaders::begin_frame
|
||||
//============================================================
|
||||
|
||||
void shaders::begin_frame()
|
||||
{
|
||||
record_texture();
|
||||
}
|
||||
|
||||
|
||||
//============================================================
|
||||
// shaders::blit
|
||||
//============================================================
|
||||
@ -1009,24 +886,6 @@ void shaders::blit(
|
||||
}
|
||||
|
||||
|
||||
//============================================================
|
||||
// shaders::end_frame
|
||||
//============================================================
|
||||
|
||||
void shaders::end_frame()
|
||||
{
|
||||
if (!enabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (render_snap && snap_rendered)
|
||||
{
|
||||
render_snapshot(snap_target);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================
|
||||
// shaders::find_render_target
|
||||
//============================================================
|
||||
@ -1400,8 +1259,6 @@ int shaders::vector_pass(d3d_render_target *rt, int source_index, poly_info *pol
|
||||
|
||||
curr_effect = vector_effect;
|
||||
curr_effect->update_uniforms();
|
||||
// curr_effect->set_float("TimeRatio", options->vector_time_ratio);
|
||||
// curr_effect->set_float("TimeScale", options->vector_time_scale);
|
||||
curr_effect->set_float("LengthRatio", options->vector_length_ratio);
|
||||
curr_effect->set_float("LengthScale", options->vector_length_scale);
|
||||
curr_effect->set_float("BeamSmooth", options->vector_beam_smooth);
|
||||
@ -1440,15 +1297,15 @@ int shaders::screen_pass(d3d_render_target *rt, int source_index, poly_info *pol
|
||||
// we do not clear the backbuffer here because multiple screens might be rendered into
|
||||
blit(backbuffer, false, poly->type(), vertnum, poly->count());
|
||||
|
||||
if (avi_output_file != nullptr)
|
||||
if (recording_movie)
|
||||
{
|
||||
blit(avi_final_target, false, poly->type(), vertnum, poly->count());
|
||||
blit(recorder->target_surface(), false, poly->type(), vertnum, poly->count());
|
||||
|
||||
HRESULT result = d3d->get_device()->SetRenderTarget(0, backbuffer);
|
||||
if (FAILED(result))
|
||||
{
|
||||
osd_printf_verbose("Direct3D: Error %08lX during device SetRenderTarget call\n", result);
|
||||
}
|
||||
|
||||
recorder->save_frame();
|
||||
}
|
||||
|
||||
if (render_snap)
|
||||
@ -1457,11 +1314,11 @@ int shaders::screen_pass(d3d_render_target *rt, int source_index, poly_info *pol
|
||||
|
||||
HRESULT result = d3d->get_device()->SetRenderTarget(0, backbuffer);
|
||||
if (FAILED(result))
|
||||
{
|
||||
osd_printf_verbose("Direct3D: Error %08lX during device SetRenderTarget call\n", result);
|
||||
}
|
||||
|
||||
snap_rendered = true;
|
||||
render_snapshot(snap_target);
|
||||
|
||||
render_snap = false;
|
||||
}
|
||||
|
||||
return next_index;
|
||||
@ -1875,7 +1732,8 @@ void shaders::delete_resources()
|
||||
return;
|
||||
}
|
||||
|
||||
end_avi_recording();
|
||||
recording_movie = false;
|
||||
recorder.reset();
|
||||
|
||||
if (options != nullptr)
|
||||
{
|
||||
@ -1965,30 +1823,6 @@ void shaders::delete_resources()
|
||||
black_texture = nullptr;
|
||||
}
|
||||
|
||||
if (avi_copy_texture != nullptr)
|
||||
{
|
||||
avi_copy_texture->Release();
|
||||
avi_copy_texture = nullptr;
|
||||
}
|
||||
|
||||
if (avi_copy_surface != nullptr)
|
||||
{
|
||||
avi_copy_surface->Release();
|
||||
avi_copy_surface = nullptr;
|
||||
}
|
||||
|
||||
if (avi_final_texture != nullptr)
|
||||
{
|
||||
avi_final_texture->Release();
|
||||
avi_final_texture = nullptr;
|
||||
}
|
||||
|
||||
if (avi_final_target != nullptr)
|
||||
{
|
||||
avi_final_target->Release();
|
||||
avi_final_target = nullptr;
|
||||
}
|
||||
|
||||
shadow_bitmap.reset();
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
#define __WIN_D3DHLSL__
|
||||
|
||||
#include <vector>
|
||||
#include "aviio.h"
|
||||
#include "../frontend/mame/ui/menuitem.h"
|
||||
#include "../frontend/mame/ui/slider.h"
|
||||
#include "modules/lib/osdlib.h"
|
||||
@ -158,6 +157,7 @@ private:
|
||||
class d3d_render_target;
|
||||
class cache_target;
|
||||
class renderer_d3d9;
|
||||
class movie_recorder;
|
||||
|
||||
/* hlsl_options is the information about runtime-mutable Direct3D HLSL options */
|
||||
/* in the future this will be moved into an OSD/emu shared buffer */
|
||||
@ -284,9 +284,6 @@ public:
|
||||
d3d_render_target* get_vector_target(render_primitive *prim);
|
||||
bool create_vector_target(render_primitive *prim);
|
||||
|
||||
void begin_frame();
|
||||
void end_frame();
|
||||
|
||||
void begin_draw();
|
||||
void end_draw();
|
||||
|
||||
@ -297,13 +294,9 @@ public:
|
||||
bool add_render_target(renderer_d3d9* d3d, render_primitive *prim, texture_info* texture, int source_width, int source_height, int target_width, int target_height);
|
||||
bool add_cache_target(renderer_d3d9* d3d, texture_info* texture, int source_width, int source_height, int target_width, int target_height, int screen_index);
|
||||
|
||||
void window_save();
|
||||
void window_record();
|
||||
bool recording() const { return avi_output_file != nullptr; }
|
||||
void save_snapshot();
|
||||
void record_movie();
|
||||
|
||||
void avi_update_snap(IDirect3DSurface9 *surface);
|
||||
void render_snapshot(IDirect3DSurface9 *surface);
|
||||
void record_texture();
|
||||
void init_fsfx_quad();
|
||||
|
||||
void set_texture(texture_info *info);
|
||||
@ -326,8 +319,7 @@ private:
|
||||
void blit(IDirect3DSurface9 *dst, bool clear_dst, D3DPRIMITIVETYPE prim_type, UINT32 prim_index, UINT32 prim_count);
|
||||
void enumerate_screens();
|
||||
|
||||
void end_avi_recording();
|
||||
void begin_avi_recording(const char *name);
|
||||
void render_snapshot(IDirect3DSurface9 *surface);
|
||||
|
||||
d3d_render_target* find_render_target(int source_width, int source_height, UINT32 screen_index, UINT32 page_index);
|
||||
cache_target * find_cache_target(UINT32 screen_index, int width, int height);
|
||||
@ -364,21 +356,13 @@ private:
|
||||
texture_info * shadow_texture; // shadow mask texture for post-processing shader
|
||||
hlsl_options * options; // current options
|
||||
|
||||
avi_file::ptr avi_output_file; // AVI file
|
||||
bitmap_rgb32 avi_snap; // AVI snapshot
|
||||
int avi_frame; // AVI frame
|
||||
attotime avi_frame_period; // AVI frame period
|
||||
attotime avi_next_frame_time; // AVI next frame time
|
||||
IDirect3DSurface9 * avi_copy_surface; // AVI destination surface in system memory
|
||||
IDirect3DTexture9 * avi_copy_texture; // AVI destination texture in system memory
|
||||
IDirect3DSurface9 * avi_final_target; // AVI upscaled surface
|
||||
IDirect3DTexture9 * avi_final_texture; // AVI upscaled texture
|
||||
|
||||
IDirect3DSurface9 * black_surface; // black dummy surface
|
||||
IDirect3DTexture9 * black_texture; // black dummy texture
|
||||
|
||||
bool recording_movie; // ongoing movie recording
|
||||
std::unique_ptr<movie_recorder> recorder; // HLSL post-render movie recorder
|
||||
|
||||
bool render_snap; // whether or not to take HLSL post-render snapshot
|
||||
bool snap_rendered; // whether we just rendered our HLSL post-render shot or not
|
||||
IDirect3DSurface9 * snap_copy_target; // snapshot destination surface in system memory
|
||||
IDirect3DTexture9 * snap_copy_texture; // snapshot destination surface in system memory
|
||||
IDirect3DSurface9 * snap_target; // snapshot upscaled surface
|
||||
|
@ -270,7 +270,7 @@ void renderer_bgfx::record()
|
||||
}
|
||||
else
|
||||
{
|
||||
m_avi_writer->record(m_options.bgfx_avi_name());
|
||||
m_avi_writer->record();
|
||||
m_avi_target = m_targets->create_target("avibuffer", bgfx::TextureFormat::RGBA8, m_width[0], m_height[0], TARGET_STYLE_CUSTOM, false, true, 1, 0);
|
||||
m_avi_texture = bgfx::createTexture2D(m_width[0], m_height[0], 1, bgfx::TextureFormat::RGBA8, BGFX_TEXTURE_BLIT_DST | BGFX_TEXTURE_READ_BACK);
|
||||
}
|
||||
|
@ -142,12 +142,12 @@ void renderer_d3d9::toggle_fsfx()
|
||||
|
||||
void renderer_d3d9::record()
|
||||
{
|
||||
get_shaders()->window_record();
|
||||
get_shaders()->record_movie();
|
||||
}
|
||||
|
||||
void renderer_d3d9::save()
|
||||
{
|
||||
get_shaders()->window_save();
|
||||
get_shaders()->save_snapshot();
|
||||
}
|
||||
|
||||
|
||||
@ -671,8 +671,6 @@ void renderer_d3d9::begin_frame()
|
||||
if (FAILED(result))
|
||||
osd_printf_verbose("Direct3D: Error %08lX during device clear call\n", result);
|
||||
|
||||
m_shaders->begin_frame();
|
||||
|
||||
win->m_primlist->acquire_lock();
|
||||
|
||||
// first update any textures
|
||||
@ -740,8 +738,6 @@ void renderer_d3d9::end_frame()
|
||||
// flush any pending polygons
|
||||
primitive_flush_pending();
|
||||
|
||||
m_shaders->end_frame();
|
||||
|
||||
// finish the scene
|
||||
HRESULT result = m_device->EndScene();
|
||||
if (FAILED(result))
|
||||
|
@ -160,7 +160,6 @@ const options_entry windows_options::s_option_entries[] =
|
||||
{ WINOPTION_HLSLPATH, "hlsl", OPTION_STRING, "path to hlsl files" },
|
||||
{ WINOPTION_HLSL_ENABLE";hlsl", "0", OPTION_BOOLEAN, "enables HLSL post-processing (PS3.0 required)" },
|
||||
{ WINOPTION_HLSL_OVERSAMPLING, "0", OPTION_BOOLEAN, "enables HLSL oversampling" },
|
||||
{ WINOPTION_HLSL_WRITE, nullptr, OPTION_STRING, "enables HLSL AVI writing (huge disk bandwidth suggested)" },
|
||||
{ WINOPTION_HLSL_SNAP_WIDTH, "2048", OPTION_STRING, "HLSL upscaled-snapshot width" },
|
||||
{ WINOPTION_HLSL_SNAP_HEIGHT, "1536", OPTION_STRING, "HLSL upscaled-snapshot height" },
|
||||
{ WINOPTION_SHADOW_MASK_TILE_MODE, "0", OPTION_INTEGER, "shadow mask tile mode (0 for screen based, 1 for source based)" },
|
||||
|
@ -29,7 +29,6 @@
|
||||
#define WINOPTION_HLSLPATH "hlslpath"
|
||||
#define WINOPTION_HLSL_ENABLE "hlsl_enable"
|
||||
#define WINOPTION_HLSL_OVERSAMPLING "hlsl_oversampling"
|
||||
#define WINOPTION_HLSL_WRITE "hlsl_write"
|
||||
#define WINOPTION_HLSL_SNAP_WIDTH "hlsl_snap_width"
|
||||
#define WINOPTION_HLSL_SNAP_HEIGHT "hlsl_snap_height"
|
||||
#define WINOPTION_SHADOW_MASK_TILE_MODE "shadow_mask_tile_mode"
|
||||
@ -130,7 +129,6 @@ public:
|
||||
const char *screen_post_fx_dir() const { return value(WINOPTION_HLSLPATH); }
|
||||
bool d3d_hlsl_enable() const { return bool_value(WINOPTION_HLSL_ENABLE); }
|
||||
bool d3d_hlsl_oversampling() const { return bool_value(WINOPTION_HLSL_OVERSAMPLING); }
|
||||
const char *d3d_hlsl_write() const { return value(WINOPTION_HLSL_WRITE); }
|
||||
int d3d_snap_width() const { return int_value(WINOPTION_HLSL_SNAP_WIDTH); }
|
||||
int d3d_snap_height() const { return int_value(WINOPTION_HLSL_SNAP_HEIGHT); }
|
||||
int screen_shadow_mask_tile_mode() const { return int_value(WINOPTION_SHADOW_MASK_TILE_MODE); }
|
||||
|
Loading…
Reference in New Issue
Block a user