summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--scripts/src/osd/modules.lua2
-rw-r--r--src/emu/sound.cpp1
-rw-r--r--src/osd/modules/input/input_sdlcommon.cpp9
-rw-r--r--src/osd/modules/input/input_windows.cpp3
-rw-r--r--src/osd/modules/lib/osdobj_common.cpp17
-rw-r--r--src/osd/modules/lib/osdobj_common.h3
-rw-r--r--src/osd/modules/osdwindow.h1
-rw-r--r--src/osd/modules/render/aviwrite.cpp161
-rw-r--r--src/osd/modules/render/aviwrite.h51
-rw-r--r--src/osd/modules/render/bgfx/target.h1
-rw-r--r--src/osd/modules/render/bgfx/targetmanager.cpp2
-rw-r--r--src/osd/modules/render/bgfx/targetmanager.h2
-rw-r--r--src/osd/modules/render/drawbgfx.cpp315
-rw-r--r--src/osd/modules/render/drawbgfx.h29
-rw-r--r--src/osd/osdepend.h1
-rw-r--r--src/osd/sdl/video.cpp3
-rw-r--r--src/osd/windows/video.cpp14
-rw-r--r--src/osd/windows/window.cpp6
-rw-r--r--src/osd/windows/winmain.h9
19 files changed, 437 insertions, 193 deletions
diff --git a/scripts/src/osd/modules.lua b/scripts/src/osd/modules.lua
index afbdd78470f..aa5cb7357d5 100644
--- a/scripts/src/osd/modules.lua
+++ b/scripts/src/osd/modules.lua
@@ -156,6 +156,8 @@ function osdmodulesbuild()
files {
MAME_DIR .. "src/osd/modules/render/drawbgfx.cpp",
+ MAME_DIR .. "src/osd/modules/render/aviwrite.cpp",
+ MAME_DIR .. "src/osd/modules/render/aviwrite.h",
MAME_DIR .. "src/osd/modules/render/bgfxutil.cpp",
MAME_DIR .. "src/osd/modules/render/bgfxutil.h",
MAME_DIR .. "src/osd/modules/render/binpacker.cpp",
diff --git a/src/emu/sound.cpp b/src/emu/sound.cpp
index 12093cb0689..eedab51e78b 100644
--- a/src/emu/sound.cpp
+++ b/src/emu/sound.cpp
@@ -1075,6 +1075,7 @@ void sound_manager::update(void *ptr, int param)
{
if (!m_nosound_mode)
machine().osd().update_audio_stream(finalmix, finalmix_offset / 2);
+ machine().osd().add_audio_to_recording(finalmix, finalmix_offset / 2);
machine().video().add_sound_to_recording(finalmix, finalmix_offset / 2);
if (m_wavfile != nullptr)
wav_add_data_16(m_wavfile, finalmix, finalmix_offset);
diff --git a/src/osd/modules/input/input_sdlcommon.cpp b/src/osd/modules/input/input_sdlcommon.cpp
index 0f6116fa048..10d9f7b3b52 100644
--- a/src/osd/modules/input/input_sdlcommon.cpp
+++ b/src/osd/modules/input/input_sdlcommon.cpp
@@ -233,7 +233,14 @@ void sdl_osd_interface::customize_input_type_list(simple_list<input_type_entry>
entry.configure_osd("INCREASE_PRESCALE", "Increase Prescaling");
entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F7, KEYCODE_LCONTROL);
break;
- // add a Not lcrtl condition to the load state key
+
+ // lshift-lalt-F12 for fullscreen video (BGFX)
+ case IPT_OSD_8:
+ entry.configure_osd("RENDER_AVI", "Record Rendered Video");
+ entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F12, KEYCODE_LSHIFT, KEYCODE_LALT);
+ break;
+
+ // add a Not lcrtl condition to the load state key
case IPT_UI_LOAD_STATE:
entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F7, input_seq::not_code, KEYCODE_LCONTROL, input_seq::not_code, KEYCODE_LSHIFT);
break;
diff --git a/src/osd/modules/input/input_windows.cpp b/src/osd/modules/input/input_windows.cpp
index 2132247b828..f80a4d57459 100644
--- a/src/osd/modules/input/input_windows.cpp
+++ b/src/osd/modules/input/input_windows.cpp
@@ -98,11 +98,12 @@ void windows_osd_interface::customize_input_type_list(simple_list<input_type_ent
entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F12, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_LALT);
break;
- // lshift-lalt-F12 for fullscreen video (HLSL)
+ // lshift-lalt-F12 for fullscreen video (HLSL, BGFX)
case IPT_OSD_3:
entry.configure_osd("RENDER_AVI", "Record Rendered Video");
entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F12, KEYCODE_LSHIFT, KEYCODE_LALT);
break;
+
// add a NOT-lalt to our default shift-F12
case IPT_UI_RECORD_MOVIE: // emu/input.c: input_seq(KEYCODE_F12, KEYCODE_LSHIFT)
entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F12, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_LALT);
diff --git a/src/osd/modules/lib/osdobj_common.cpp b/src/osd/modules/lib/osdobj_common.cpp
index e8f344028b0..b6114acb98c 100644
--- a/src/osd/modules/lib/osdobj_common.cpp
+++ b/src/osd/modules/lib/osdobj_common.cpp
@@ -147,6 +147,7 @@ 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 }
@@ -422,8 +423,8 @@ void osd_common_t::init(running_machine &machine)
// ensure we get called on the way out
machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(osd_common_t::osd_exit), this));
-
-
+
+
/* now setup watchdog */
int watchdog_timeout = options.watchdog();
@@ -559,6 +560,18 @@ std::vector<ui_menu_item> osd_common_t::get_slider_list()
return m_sliders;
}
+
+//-------------------------------------------------
+// add_audio_to_recording - append audio samples
+// to an AVI recording if one is active
+//-------------------------------------------------
+
+void osd_common_t::add_audio_to_recording(const INT16 *buffer, int samples_this_frame)
+{
+ // Do nothing
+}
+
+
//-------------------------------------------------
// execute_command - execute a command not yet
// handled by the core
diff --git a/src/osd/modules/lib/osdobj_common.h b/src/osd/modules/lib/osdobj_common.h
index 00778fac569..0d86d412cf9 100644
--- a/src/osd/modules/lib/osdobj_common.h
+++ b/src/osd/modules/lib/osdobj_common.h
@@ -84,6 +84,7 @@ class ui_menu_item;
#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,6 +158,7 @@ public:
const 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[];
@@ -192,6 +194,7 @@ public:
virtual void customize_input_type_list(simple_list<input_type_entry> &typelist) override;
// video overridables
+ virtual void add_audio_to_recording(const INT16 *buffer, int samples_this_frame) override;
virtual std::vector<ui_menu_item> get_slider_list() override;
// command option overrides
diff --git a/src/osd/modules/osdwindow.h b/src/osd/modules/osdwindow.h
index 1361ff50c9f..218e48145d5 100644
--- a/src/osd/modules/osdwindow.h
+++ b/src/osd/modules/osdwindow.h
@@ -197,6 +197,7 @@ public:
virtual int create() = 0;
virtual render_primitive_list *get_primitives() = 0;
+ virtual void add_audio_to_recording(const INT16 *buffer, int samples_this_frame) { }
virtual std::vector<ui_menu_item> get_slider_list() { return m_sliders; }
virtual int draw(const int update) = 0;
virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) { return 0; };
diff --git a/src/osd/modules/render/aviwrite.cpp b/src/osd/modules/render/aviwrite.cpp
new file mode 100644
index 00000000000..6a27c567a43
--- /dev/null
+++ b/src/osd/modules/render/aviwrite.cpp
@@ -0,0 +1,161 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+//============================================================
+//
+// aviwrite.cpp - AVI screenshot writer class
+//
+//============================================================
+
+#include "aviwrite.h"
+#include "modules/lib/osdobj_common.h"
+
+avi_write::avi_write(running_machine& machine, uint32_t width, uint32_t height)
+ : m_machine(machine)
+ , m_recording(false)
+ , m_width(width)
+ , m_height(height)
+ , m_output_file(nullptr)
+ , m_frame(0)
+{
+}
+
+avi_write::~avi_write()
+{
+ if (m_recording)
+ {
+ stop();
+ }
+}
+
+void avi_write::record(std::string name)
+{
+ if (m_recording)
+ {
+ end_avi_recording();
+ }
+
+ if (name != "")
+ {
+ begin_avi_recording(name);
+ }
+}
+
+void avi_write::stop()
+{
+ osd_printf_info("Stopping AVI recording after %d frames.\n", m_frame);
+ end_avi_recording();
+}
+
+void avi_write::begin_avi_recording(std::string name)
+{
+ // stop any existing recording
+ end_avi_recording();
+
+ // reset the state
+ m_frame = 0;
+ m_next_frame_time = m_machine.time();
+
+ // build up information about this new movie
+ avi_file::movie_info info;
+ info.video_format = 0;
+ info.video_timescale = 1000 * ((m_machine.first_screen() != nullptr) ? ATTOSECONDS_TO_HZ(m_machine.first_screen()->frame_period().m_attoseconds) : screen_device::DEFAULT_FRAME_RATE);
+ info.video_sampletime = 1000;
+ info.video_numsamples = 0;
+ info.video_width = m_width;
+ info.video_height = m_height;
+ info.video_depth = 24;
+
+ info.audio_format = 0;
+ info.audio_timescale = m_machine.sample_rate();
+ info.audio_sampletime = 1;
+ info.audio_numsamples = 0;
+ info.audio_channels = 2;
+ info.audio_samplebits = 16;
+ info.audio_samplerate = m_machine.sample_rate();
+
+ // 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();
+ }
+ }
+
+ if (filerr == osd_file::error::NONE)
+ {
+ // 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)
+ {
+ osd_printf_error("Error creating AVI: %s\n", avi_file::error_string(avierr));
+ }
+ else
+ {
+ m_recording = true;
+ }
+ }
+}
+
+void avi_write::end_avi_recording()
+{
+ if (m_output_file)
+ {
+ m_output_file.reset();
+ }
+
+ m_recording = false;
+ m_output_file = nullptr;
+ m_frame = 0;
+}
+
+void avi_write::video_frame(bitmap_rgb32& snap)
+{
+ // get the current time
+ attotime curtime = m_machine.time();
+
+ // loop until we hit the right time
+ while (m_next_frame_time <= curtime)
+ {
+ // handle an AVI recording
+ // write the next frame
+ avi_file::error avierr = m_output_file->append_video_frame(snap);
+ if (avierr != avi_file::error::NONE)
+ {
+ osd_printf_error("Error while logging AVI video frame: %s\n", avi_file::error_string(avierr));
+ osd_printf_error("Stopping AVI recording.\n");
+ end_avi_recording();
+ return;
+ }
+
+ // advance time
+ m_next_frame_time += m_frame_period;
+ m_frame++;
+ }
+}
+
+void avi_write::audio_frame(const INT16 *buffer, int samples_this_frame)
+{
+ // only record if we have a file
+ if (m_output_file != nullptr)
+ {
+ // write the next frame
+ avi_file::error avierr = m_output_file->append_sound_samples(0, buffer + 0, samples_this_frame, 1);
+ if (avierr == avi_file::error::NONE)
+ avierr = m_output_file->append_sound_samples(1, buffer + 1, samples_this_frame, 1);
+ if (avierr != avi_file::error::NONE)
+ {
+ osd_printf_error("Error while logging AVI audio frame: %s\n", avi_file::error_string(avierr));
+ osd_printf_error("Stopping AVI recording.\n");
+ end_avi_recording();
+ }
+ }
+} \ No newline at end of file
diff --git a/src/osd/modules/render/aviwrite.h b/src/osd/modules/render/aviwrite.h
new file mode 100644
index 00000000000..2a948964eb8
--- /dev/null
+++ b/src/osd/modules/render/aviwrite.h
@@ -0,0 +1,51 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+//============================================================
+//
+// aviwrite.h - AVI screenshot writer class
+//
+//============================================================
+
+#pragma once
+
+#ifndef __RENDER_AVIWRITE__
+#define __RENDER_AVIWRITE__
+
+#include "emu.h"
+#include "aviio.h"
+
+class running_machine;
+
+class avi_write
+{
+public:
+ avi_write(running_machine& machine, uint32_t width, uint32_t height);
+ ~avi_write();
+
+ void record(std::string name);
+ void stop();
+ void audio_frame(const INT16 *buffer, int samples_this_frame);
+ void video_frame(bitmap_rgb32& snap);
+
+ // Getters
+ bool recording() const { return m_recording; }
+
+private:
+ void begin_avi_recording(std::string name);
+ void end_avi_recording();
+
+ running_machine& m_machine;
+
+ bool m_recording;
+
+ uint32_t m_width;
+ uint32_t m_height;
+
+ avi_file::ptr m_output_file;
+
+ int m_frame;
+ attotime m_frame_period;
+ attotime m_next_frame_time;
+};
+
+#endif // __RENDER_AVIWRITE__ \ No newline at end of file
diff --git a/src/osd/modules/render/bgfx/target.h b/src/osd/modules/render/bgfx/target.h
index 76d4c374c7e..d521d2aa3d2 100644
--- a/src/osd/modules/render/bgfx/target.h
+++ b/src/osd/modules/render/bgfx/target.h
@@ -52,6 +52,7 @@ public:
private:
std::string m_name;
bgfx::TextureFormat::Enum m_format;
+ bool m_readback;
bgfx::FrameBufferHandle* m_targets;
bgfx::TextureHandle* m_textures;
diff --git a/src/osd/modules/render/bgfx/targetmanager.cpp b/src/osd/modules/render/bgfx/targetmanager.cpp
index e17b0e6915a..40895727437 100644
--- a/src/osd/modules/render/bgfx/targetmanager.cpp
+++ b/src/osd/modules/render/bgfx/targetmanager.cpp
@@ -59,7 +59,7 @@ bgfx_target* target_manager::create_target(std::string name, bgfx::TextureFormat
void target_manager::destroy_target(std::string name, uint32_t screen)
{
- std::string full_name = name + std::to_string(screen);
+ std::string full_name = (screen < 0) ? name : (name + std::to_string(screen));
if (m_targets[full_name] != nullptr)
{
delete m_targets[full_name];
diff --git a/src/osd/modules/render/bgfx/targetmanager.h b/src/osd/modules/render/bgfx/targetmanager.h
index 04ac4252f9d..0ab45e638d1 100644
--- a/src/osd/modules/render/bgfx/targetmanager.h
+++ b/src/osd/modules/render/bgfx/targetmanager.h
@@ -31,7 +31,7 @@ public:
~target_manager();
bgfx_target* create_target(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, uint32_t style, bool double_buffer, bool filter, uint16_t scale, uint32_t screen);
- void destroy_target(std::string name, uint32_t screen);
+ void destroy_target(std::string name, uint32_t screen = -1);
bgfx_target* create_backbuffer(void *handle, uint16_t width, uint16_t height);
void update_target_sizes(uint32_t screen, uint16_t width, uint16_t height, uint32_t style);
diff --git a/src/osd/modules/render/drawbgfx.cpp b/src/osd/modules/render/drawbgfx.cpp
index 51806233ea6..f90e7f060e1 100644
--- a/src/osd/modules/render/drawbgfx.cpp
+++ b/src/osd/modules/render/drawbgfx.cpp
@@ -20,7 +20,7 @@
#include "emu.h"
#include "window.h"
#include "rendutil.h"
-#include "aviio.h"
+#include "aviwrite.h"
#include <bgfx/bgfxplatform.h>
#include <bgfx/bgfx.h>
@@ -82,8 +82,8 @@ renderer_bgfx::renderer_bgfx(osd_window *w)
, m_options(downcast<osd_options &>(w->machine().options()))
, m_dimensions(0, 0)
, m_max_view(0)
- , m_avi_output_file(nullptr)
- , m_avi_frame(0)
+ , m_avi_writer(nullptr)
+ , m_avi_target(nullptr)
{
m_options = downcast<osd_options &>(window().machine().options());
}
@@ -94,6 +94,19 @@ renderer_bgfx::renderer_bgfx(osd_window *w)
renderer_bgfx::~renderer_bgfx()
{
+ if (m_avi_writer != nullptr && m_avi_writer->recording())
+ {
+ m_avi_writer->stop();
+
+ m_targets->destroy_target("avibuffer0");
+ m_avi_target = nullptr;
+
+ bgfx::destroyTexture(m_avi_texture);
+
+ delete m_avi_writer;
+ delete [] m_avi_data;
+ }
+
// Cleanup.
delete m_chains;
delete m_effects;
@@ -236,29 +249,27 @@ int renderer_bgfx::create()
// renderer_bgfx::record
//============================================================
-#ifndef OSD_SDL
void renderer_bgfx::record()
{
- std::string filename("test.avi");//m_options.d3d_hlsl_write());
+ if (m_avi_writer == nullptr || window().m_index > 0)
+ {
+ return;
+ }
- if (m_avi_output_file != nullptr)
+ if (m_avi_writer->recording())
{
- end_avi_recording();
+ m_avi_writer->stop();
+ m_targets->destroy_target("avibuffer0");
+ m_avi_target = nullptr;
+ bgfx::destroyTexture(m_avi_texture);
}
- else if (filename[0] != 0)
+ else
{
- begin_avi_recording(filename);
+ m_avi_writer->record(m_options.bgfx_avi_name());
+ 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);
}
}
-#endif
-
-void renderer_bgfx::end_avi_recording()
-{
-}
-
-void renderer_bgfx::begin_avi_recording(std::string filename)
-{
-}
void renderer_bgfx::exit()
{
@@ -291,26 +302,18 @@ int renderer_bgfx::xy_to_render_target(int x, int y, int *xt, int *yt)
bgfx::VertexDecl ScreenVertex::ms_decl;
-void renderer_bgfx::put_packed_quad(render_primitive *prim, UINT32 hash, ScreenVertex* vertex)
+void renderer_bgfx::put_packed_quad(render_primitive *prim, UINT32 hash, ScreenVertex* vertices)
{
rectangle_packer::packed_rectangle& rect = m_hash_to_entry[hash];
- float u0 = float(rect.x()) / float(CACHE_SIZE);
- float v0 = float(rect.y()) / float(CACHE_SIZE);
- float u1 = u0 + float(rect.width()) / float(CACHE_SIZE);
- float v1 = v0 + float(rect.height()) / float(CACHE_SIZE);
- u1 -= 0.5f / float(CACHE_SIZE);
- v1 -= 0.5f / float(CACHE_SIZE);
- u0 += 0.5f / float(CACHE_SIZE);
- v0 += 0.5f / float(CACHE_SIZE);
+ float size = float(CACHE_SIZE);
+ float u0 = (float(rect.x()) + 0.5f) / size;
+ float v0 = (float(rect.y()) + 0.5f) / size;
+ float u1 = u0 + (float(rect.width()) - 1.0f) / size;
+ float v1 = v0 + (float(rect.height()) - 1.0f) / size;
UINT32 rgba = u32Color(prim->color.r * 255, prim->color.g * 255, prim->color.b * 255, prim->color.a * 255);
- const float x0 = prim->bounds.x0;
- const float x1 = prim->bounds.x1;
- const float y0 = prim->bounds.y0;
- const float y1 = prim->bounds.y1;
-
- float x[4] = { x0, x1, x0, x1 };
- float y[4] = { y0, y0, y1, y1 };
+ float x[4] = { prim->bounds.x0, prim->bounds.x1, prim->bounds.x0, prim->bounds.x1 };
+ float y[4] = { prim->bounds.y0, prim->bounds.y0, prim->bounds.y1, prim->bounds.y1 };
float u[4] = { u0, u1, u0, u1 };
float v[4] = { v0, v0, v1, v1 };
@@ -336,99 +339,39 @@ void renderer_bgfx::put_packed_quad(render_primitive *prim, UINT32 hash, ScreenV
std::swap(v[1], v[3]);
}
- vertex[0].m_x = x[0]; // 0
- vertex[0].m_y = y[0];
- vertex[0].m_z = 0;
- vertex[0].m_rgba = rgba;
- vertex[0].m_u = u[0];
- vertex[0].m_v = v[0];
-
- vertex[1].m_x = x[1]; // 1
- vertex[1].m_y = y[1];
- vertex[1].m_z = 0;
- vertex[1].m_rgba = rgba;
- vertex[1].m_u = u[1];
- vertex[1].m_v = v[1];
-
- vertex[2].m_x = x[3]; // 3
- vertex[2].m_y = y[3];
- vertex[2].m_z = 0;
- vertex[2].m_rgba = rgba;
- vertex[2].m_u = u[3];
- vertex[2].m_v = v[3];
-
- vertex[3].m_x = x[3]; // 3
- vertex[3].m_y = y[3];
- vertex[3].m_z = 0;
- vertex[3].m_rgba = rgba;
- vertex[3].m_u = u[3];
- vertex[3].m_v = v[3];
-
- vertex[4].m_x = x[2]; // 2
- vertex[4].m_y = y[2];
- vertex[4].m_z = 0;
- vertex[4].m_rgba = rgba;
- vertex[4].m_u = u[2];
- vertex[4].m_v = v[2];
-
- vertex[5].m_x = x[0]; // 0
- vertex[5].m_y = y[0];
- vertex[5].m_z = 0;
- vertex[5].m_rgba = rgba;
- vertex[5].m_u = u[0];
- vertex[5].m_v = v[0];
+ vertex(&vertices[0], x[0], y[0], 0, rgba, u[0], v[0]);
+ vertex(&vertices[1], x[1], y[1], 0, rgba, u[1], v[1]);
+ vertex(&vertices[2], x[3], y[3], 0, rgba, u[3], v[3]);
+ vertex(&vertices[3], x[3], y[3], 0, rgba, u[3], v[3]);
+ vertex(&vertices[4], x[2], y[2], 0, rgba, u[2], v[2]);
+ vertex(&vertices[5], x[0], y[0], 0, rgba, u[0], v[0]);
+}
+
+void renderer_bgfx::vertex(ScreenVertex* vertex, float x, float y, float z, uint32_t rgba, float u, float v)
+{
+ vertex->m_x = x;
+ vertex->m_y = y;
+ vertex->m_z = z;
+ vertex->m_rgba = rgba;
+ vertex->m_u = u;
+ vertex->m_v = v;
}
void renderer_bgfx::render_post_screen_quad(int view, render_primitive* prim, bgfx::TransientVertexBuffer* buffer, int32_t screen)
{
- ScreenVertex* vertex = reinterpret_cast<ScreenVertex*>(buffer->data);
+ ScreenVertex* vertices = reinterpret_cast<ScreenVertex*>(buffer->data);
float x[4] = { prim->bounds.x0, prim->bounds.x1, prim->bounds.x0, prim->bounds.x1 };
float y[4] = { prim->bounds.y0, prim->bounds.y0, prim->bounds.y1, prim->bounds.y1 };
float u[4] = { prim->texcoords.tl.u, prim->texcoords.tr.u, prim->texcoords.bl.u, prim->texcoords.br.u };
float v[4] = { prim->texcoords.tl.v, prim->texcoords.tr.v, prim->texcoords.bl.v, prim->texcoords.br.v };
- vertex[0].m_x = x[0];
- vertex[0].m_y = y[0];
- vertex[0].m_z = 0;
- vertex[0].m_rgba = 0xffffffff;
- vertex[0].m_u = u[0];
- vertex[0].m_v = v[0];
-
- vertex[1].m_x = x[1];
- vertex[1].m_y = y[1];
- vertex[1].m_z = 0;
- vertex[1].m_rgba = 0xffffffff;
- vertex[1].m_u = u[1];
- vertex[1].m_v = v[1];
-
- vertex[2].m_x = x[3];
- vertex[2].m_y = y[3];
- vertex[2].m_z = 0;
- vertex[2].m_rgba = 0xffffffff;
- vertex[2].m_u = u[3];
- vertex[2].m_v = v[3];
-
- vertex[3].m_x = x[3];
- vertex[3].m_y = y[3];
- vertex[3].m_z = 0;
- vertex[3].m_rgba = 0xffffffff;
- vertex[3].m_u = u[3];
- vertex[3].m_v = v[3];
-
- vertex[4].m_x = x[2];
- vertex[4].m_y = y[2];
- vertex[4].m_z = 0;
- vertex[4].m_rgba = 0xffffffff;
- vertex[4].m_u = u[2];
- vertex[4].m_v = v[2];
-
- vertex[5].m_x = x[0];
- vertex[5].m_y = y[0];
- vertex[5].m_z = 0;
- vertex[5].m_rgba = 0xffffffff;
- vertex[5].m_u = u[0];
- vertex[5].m_v = v[0];
+ vertex(&vertices[0], x[0], y[0], 0, 0xffffffff, u[0], v[0]);
+ vertex(&vertices[1], x[1], y[1], 0, 0xffffffff, u[1], v[1]);
+ vertex(&vertices[2], x[3], y[3], 0, 0xffffffff, u[3], v[3]);
+ vertex(&vertices[3], x[3], y[3], 0, 0xffffffff, u[3], v[3]);
+ vertex(&vertices[4], x[2], y[2], 0, 0xffffffff, u[2], v[2]);
+ vertex(&vertices[5], x[0], y[0], 0, 0xffffffff, u[0], v[0]);
uint32_t texture_flags = BGFX_TEXTURE_U_CLAMP | BGFX_TEXTURE_V_CLAMP;
if (video_config.filter == 0)
@@ -442,53 +385,53 @@ void renderer_bgfx::render_post_screen_quad(int view, render_primitive* prim, bg
m_screen_effect[blend]->submit(view);
}
-void renderer_bgfx::render_textured_quad(render_primitive* prim, bgfx::TransientVertexBuffer* buffer)
+void renderer_bgfx::render_avi_quad()
{
- ScreenVertex* vertex = reinterpret_cast<ScreenVertex*>(buffer->data);
+ bgfx::setViewSeq(s_current_view, true);
+ bgfx::setViewRect(s_current_view, 0, 0, m_width[0], m_height[0]);
+ bgfx::setViewClear(s_current_view, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x00000000, 1.0f, 0);
+
+ setup_matrices(s_current_view, false);
+
+ bgfx::TransientVertexBuffer buffer;
+ bgfx::allocTransientVertexBuffer(&buffer, 6, ScreenVertex::ms_decl);
+ ScreenVertex* vertices = reinterpret_cast<ScreenVertex*>(buffer.data);
+
+ float x[4] = { 0.0f, float(m_width[0]), 0.0f, float(m_width[0]) };
+ float y[4] = { 0.0f, 0.0f, float(m_height[0]), float(m_height[0]) };
+ float u[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
+ float v[4] = { 0.0f, 0.0f, 1.0f, 1.0f };
+ UINT32 rgba = 0xffffffff;
+
+ vertex(&vertices[0], x[0], y[0], 0, rgba, u[0], v[0]);
+ vertex(&vertices[1], x[1], y[1], 0, rgba, u[1], v[1]);
+ vertex(&vertices[2], x[3], y[3], 0, rgba, u[3], v[3]);
+ vertex(&vertices[3], x[3], y[3], 0, rgba, u[3], v[3]);
+ vertex(&vertices[4], x[2], y[2], 0, rgba, u[2], v[2]);
+ vertex(&vertices[5], x[0], y[0], 0, rgba, u[0], v[0]);
+
+ bgfx::setVertexBuffer(&buffer);
+ bgfx::setTexture(0, m_gui_effect[PRIMFLAG_GET_BLENDMODE(BLENDMODE_NONE)]->uniform("s_tex")->handle(), m_avi_target->texture());
+ m_gui_effect[PRIMFLAG_GET_BLENDMODE(BLENDMODE_NONE)]->submit(s_current_view);
+ s_current_view++;
+}
+void renderer_bgfx::render_textured_quad(render_primitive* prim, bgfx::TransientVertexBuffer* buffer)
+{
+ ScreenVertex* vertices = reinterpret_cast<ScreenVertex*>(buffer->data);
UINT32 rgba = u32Color(prim->color.r * 255, prim->color.g * 255, prim->color.b * 255, prim->color.a * 255);
- vertex[0].m_x = prim->bounds.x0;
- vertex[0].m_y = prim->bounds.y0;
- vertex[0].m_z = 0;
- vertex[0].m_rgba = rgba;
- vertex[0].m_u = prim->texcoords.tl.u;
- vertex[0].m_v = prim->texcoords.tl.v;
-
- vertex[1].m_x = prim->bounds.x1;
- vertex[1].m_y = prim->bounds.y0;
- vertex[1].m_z = 0;
- vertex[1].m_rgba = rgba;
- vertex[1].m_u = prim->texcoords.tr.u;
- vertex[1].m_v = prim->texcoords.tr.v;
-
- vertex[2].m_x = prim->bounds.x1;
- vertex[2].m_y = prim->bounds.y1;
- vertex[2].m_z = 0;
- vertex[2].m_rgba = rgba;
- vertex[2].m_u = prim->texcoords.br.u;
- vertex[2].m_v = prim->texcoords.br.v;
-
- vertex[3].m_x = prim->bounds.x1;
- vertex[3].m_y = prim->bounds.y1;
- vertex[3].m_z = 0;
- vertex[3].m_rgba = rgba;
- vertex[3].m_u = prim->texcoords.br.u;
- vertex[3].m_v = prim->texcoords.br.v;
-
- vertex[4].m_x = prim->bounds.x0;
- vertex[4].m_y = prim->bounds.y1;
- vertex[4].m_z = 0;
- vertex[4].m_rgba = rgba;
- vertex[4].m_u = prim->texcoords.bl.u;
- vertex[4].m_v = prim->texcoords.bl.v;
-
- vertex[5].m_x = prim->bounds.x0;
- vertex[5].m_y = prim->bounds.y0;
- vertex[5].m_z = 0;
- vertex[5].m_rgba = rgba;
- vertex[5].m_u = prim->texcoords.tl.u;
- vertex[5].m_v = prim->texcoords.tl.v;
+ float x[4] = { prim->bounds.x0, prim->bounds.x1, prim->bounds.x0, prim->bounds.x1 };
+ float y[4] = { prim->bounds.y0, prim->bounds.y0, prim->bounds.y1, prim->bounds.y1 };
+ float u[4] = { prim->texcoords.tl.u, prim->texcoords.tr.u, prim->texcoords.bl.u, prim->texcoords.br.u };
+ float v[4] = { prim->texcoords.tl.v, prim->texcoords.tr.v, prim->texcoords.bl.v, prim->texcoords.br.v };
+
+ vertex(&vertices[0], x[0], y[0], 0, rgba, u[0], v[0]);
+ vertex(&vertices[1], x[1], y[1], 0, rgba, u[1], v[1]);
+ vertex(&vertices[2], x[3], y[3], 0, rgba, u[3], v[3]);
+ vertex(&vertices[3], x[3], y[3], 0, rgba, u[3], v[3]);
+ vertex(&vertices[4], x[2], y[2], 0, rgba, u[2], v[2]);
+ vertex(&vertices[5], x[0], y[0], 0, rgba, u[0], v[0]);
uint32_t texture_flags = BGFX_TEXTURE_U_CLAMP | BGFX_TEXTURE_V_CLAMP;
if (video_config.filter == 0)
@@ -709,6 +652,14 @@ int renderer_bgfx::draw(int update)
if (window_index == 0)
{
s_current_view = 0;
+ if (m_avi_writer == nullptr)
+ {
+ uint32_t width = window().get_size().width();
+ uint32_t height = window().get_size().height();
+ m_avi_writer = new avi_write(window().machine(), width, height);
+ m_avi_data = new uint8_t[width * height * 4];
+ m_avi_bitmap.allocate(width, height);
+ }
}
m_seen_views.clear();
@@ -785,20 +736,50 @@ int renderer_bgfx::draw(int update)
window().m_primlist->release_lock();
- // This dummy draw call is here to make sure that view 0 is cleared
- // if no other draw calls are submitted to view 0.
- bgfx::touch(s_current_view > 0 ? s_current_view - 1 : 0);
+ // This dummy draw call is here to make sure that view 0 is cleared
+ // if no other draw calls are submitted to view 0.
+ bgfx::touch(s_current_view > 0 ? s_current_view - 1 : 0);
- // Advance to next frame. Rendering thread will be kicked to
+ // Advance to next frame. Rendering thread will be kicked to
// process submitted rendering primitives.
if (window_index == 0)
{
+ if (m_avi_writer != nullptr && m_avi_writer->recording() && window_index == 0)
+ {
+ render_avi_quad();
+ bgfx::touch(s_current_view);
+ update_recording();
+ }
+
bgfx::frame();
}
return 0;
}
+void renderer_bgfx::update_recording()
+{
+ bgfx::blit(s_current_view > 0 ? s_current_view - 1 : 0, m_avi_texture, 0, 0, m_avi_target->target());
+ bgfx::readTexture(m_avi_texture, m_avi_data);
+
+ UINT32* start = &m_avi_bitmap.pix32(0);
+ // loop over Y
+ for (int i = 0; i < m_width[0] * m_height[0] * 4; i += 4)
+ {
+ *start++ = 0xff000000 | (m_avi_data[i + 0] << 16) | (m_avi_data[i + 1] << 8) | m_avi_data[i + 2];
+ }
+
+ m_avi_writer->video_frame(m_avi_bitmap);
+}
+
+void renderer_bgfx::add_audio_to_recording(const INT16 *buffer, int samples_this_frame)
+{
+ if (m_avi_writer != nullptr && m_avi_writer->recording() && window().m_index == 0)
+ {
+ m_avi_writer->audio_frame(buffer, samples_this_frame);
+ }
+}
+
bool renderer_bgfx::update_dimensions()
{
const uint32_t window_index = window().m_index;
@@ -864,7 +845,11 @@ void renderer_bgfx::setup_view(uint32_t view_index, bool screen)
{
m_seen_views[view_index] = true;
#endif
- bgfx::setViewClear(view_index, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x00000000, 1.0f, 0);
+ if (m_avi_writer != nullptr && m_avi_writer->recording() && window().m_index == 0)
+ {
+ bgfx::setViewFrameBuffer(view_index, m_avi_target->target());
+ }
+ bgfx::setViewClear(view_index, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x00000000, 1.0f, 0);
}
setup_matrices(view_index, screen);
diff --git a/src/osd/modules/render/drawbgfx.h b/src/osd/modules/render/drawbgfx.h
index e96fd461cc1..f7da00fe787 100644
--- a/src/osd/modules/render/drawbgfx.h
+++ b/src/osd/modules/render/drawbgfx.h
@@ -13,7 +13,6 @@
#include "binpacker.h"
#include "bgfx/vertex.h"
#include "sliderdirtynotifier.h"
-#include "aviio.h"
class texture_manager;
class target_manager;
@@ -25,6 +24,7 @@ class bgfx_effect;
class bgfx_target;
class bgfx_chain;
class osd_options;
+class avi_write;
/* sdl_info is the information about SDL for the current screen */
class renderer_bgfx : public osd_renderer, public slider_dirty_notifier
@@ -39,16 +39,17 @@ public:
virtual int create() override;
virtual int draw(const int update) override;
+ virtual void add_audio_to_recording(const INT16 *buffer, int samples_this_frame) override;
virtual std::vector<ui_menu_item> get_slider_list() override;
virtual void set_sliders_dirty() override;
#ifdef OSD_SDL
virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) override;
-#else
+#endif
+
virtual void save() override { }
virtual void record() override;
virtual void toggle_fsfx() override { }
-#endif
virtual render_primitive_list *get_primitives() override
{
@@ -60,13 +61,16 @@ public:
static const char* WINDOW_PREFIX;
private:
- void end_avi_recording();
- void begin_avi_recording(std::string filename);
+ void vertex(ScreenVertex* vertex, float x, float y, float z, uint32_t rgba, float u, float v);
+ void render_avi_quad();
+ void update_recording();
- bool update_dimensions();
- void setup_view(uint32_t view_index, bool screen);
+ bool update_dimensions();
+
+ void setup_view(uint32_t view_index, bool screen);
void init_ui_view();
- void setup_matrices(uint32_t view_index, bool screen);
+
+ void setup_matrices(uint32_t view_index, bool screen);
void allocate_buffer(render_primitive *prim, UINT32 blend, bgfx::TransientVertexBuffer *buffer);
enum buffer_status
@@ -123,10 +127,11 @@ private:
int32_t m_ui_view;
uint32_t m_max_view;
- // AVI
- avi_file::ptr m_avi_output_file; // AVI file
- int m_avi_frame; // AVI frame
- attotime m_avi_frame_period; // AVI frame period
+ avi_write* m_avi_writer;
+ bgfx_target* m_avi_target;
+ bgfx::TextureHandle m_avi_texture;
+ bitmap_rgb32 m_avi_bitmap;
+ uint8_t* m_avi_data;
static const uint16_t CACHE_SIZE;
static const uint32_t PACKABLE_SIZE;
diff --git a/src/osd/osdepend.h b/src/osd/osdepend.h
index 661160cb271..e305aeb958f 100644
--- a/src/osd/osdepend.h
+++ b/src/osd/osdepend.h
@@ -79,6 +79,7 @@ public:
virtual void customize_input_type_list(simple_list<input_type_entry> &typelist) = 0;
// video overridables
+ virtual void add_audio_to_recording(const INT16 *buffer, int samples_this_frame) = 0;
virtual std::vector<ui_menu_item> get_slider_list() = 0;
// font interface
diff --git a/src/osd/sdl/video.cpp b/src/osd/sdl/video.cpp
index 8a8402e44b3..099c4bccfc9 100644
--- a/src/osd/sdl/video.cpp
+++ b/src/osd/sdl/video.cpp
@@ -314,6 +314,9 @@ static void check_osd_inputs(running_machine &machine)
if (machine.ui_input().pressed(IPT_OSD_7))
window->modify_prescale(1);
+
+ if (machine.ui_input().pressed(IPT_OSD_8))
+ window->renderer().record();
}
//============================================================
diff --git a/src/osd/windows/video.cpp b/src/osd/windows/video.cpp
index b0f28ee7d13..d73ad8bf522 100644
--- a/src/osd/windows/video.cpp
+++ b/src/osd/windows/video.cpp
@@ -51,8 +51,6 @@ osd_monitor_info *osd_monitor_info::list = NULL;
static void init_monitors(void);
-static void check_osd_inputs(running_machine &machine);
-
static float get_aspect(const char *defdata, const char *data, int report_error);
static void get_resolution(const char *defdata, const char *data, osd_window_config *config, int report_error);
@@ -180,7 +178,7 @@ void windows_osd_interface::update(bool skip_redraw)
// poll the joystick values here
winwindow_process_events(machine(), TRUE, FALSE);
poll_input(machine());
- check_osd_inputs(machine());
+ check_osd_inputs();
// if we're running, disable some parts of the debugger
if ((machine().debug_flags & DEBUG_FLAG_OSD_ENABLED) != 0)
debugger_update();
@@ -308,22 +306,22 @@ finishit:
// check_osd_inputs
//============================================================
-static void check_osd_inputs(running_machine &machine)
+void windows_osd_interface::check_osd_inputs()
{
// check for toggling fullscreen mode
- if (machine.ui_input().pressed(IPT_OSD_1))
+ if (machine().ui_input().pressed(IPT_OSD_1))
winwindow_toggle_full_screen();
// check for taking fullscreen snap
- if (machine.ui_input().pressed(IPT_OSD_2))
+ if (machine().ui_input().pressed(IPT_OSD_2))
winwindow_take_snap();
// check for taking fullscreen video
- if (machine.ui_input().pressed(IPT_OSD_3))
+ if (machine().ui_input().pressed(IPT_OSD_3))
winwindow_take_video();
// check for taking fullscreen video
- if (machine.ui_input().pressed(IPT_OSD_4))
+ if (machine().ui_input().pressed(IPT_OSD_4))
winwindow_toggle_fsfx();
}
diff --git a/src/osd/windows/window.cpp b/src/osd/windows/window.cpp
index 8938ca427ce..da6aebd07ff 100644
--- a/src/osd/windows/window.cpp
+++ b/src/osd/windows/window.cpp
@@ -286,6 +286,12 @@ void windows_osd_interface::build_slider_list()
}
}
+void windows_osd_interface::add_audio_to_recording(const INT16 *buffer, int samples_this_frame)
+{
+ win_window_info *window = win_window_list; // We only record on the first window
+ window->m_renderer->add_audio_to_recording(buffer, samples_this_frame);
+}
+
//============================================================
// winwindow_exit
// (main thread)
diff --git a/src/osd/windows/winmain.h b/src/osd/windows/winmain.h
index b41092bf500..216333dbd13 100644
--- a/src/osd/windows/winmain.h
+++ b/src/osd/windows/winmain.h
@@ -260,9 +260,12 @@ public:
virtual void init(running_machine &machine) override;
virtual void update(bool skip_redraw) override;
- // video overridables
+ // input overrideables
virtual void customize_input_type_list(simple_list<input_type_entry> &typelist) override;
+ // video overridables
+ virtual void add_audio_to_recording(const INT16 *buffer, int samples_this_frame) override;
+
virtual void video_register() override;
virtual bool video_init() override;
@@ -286,6 +289,8 @@ protected:
virtual void build_slider_list() override;
virtual void update_slider_list() override;
+ void check_osd_inputs();
+
private:
virtual void osd_exit() override;
@@ -306,7 +311,7 @@ private:
public:
MameMainApp();
- // IFrameworkView Methods.
+ // IFrameworkView Methods.
virtual void Initialize(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView);
virtual void SetWindow(Windows::UI::Core::CoreWindow^ window);
virtual void Load(Platform::String^ entryPoint);