Example #1
0
video_manager::video_manager(running_machine &machine)
	: m_machine(machine)
	, m_screenless_frame_timer(nullptr)
	, m_output_changed(false)
	, m_throttle_last_ticks(0)
	, m_throttle_realtime(attotime::zero)
	, m_throttle_emutime(attotime::zero)
	, m_throttle_history(0)
	, m_speed_last_realtime(0)
	, m_speed_last_emutime(attotime::zero)
	, m_speed_percent(1.0)
	, m_overall_real_seconds(0)
	, m_overall_real_ticks(0)
	, m_overall_emutime(attotime::zero)
	, m_overall_valid_counter(0)
	, m_throttled(machine.options().throttle())
	, m_throttle_rate(1.0f)
	, m_fastforward(false)
	, m_seconds_to_run(machine.options().seconds_to_run())
	, m_auto_frameskip(machine.options().auto_frameskip())
	, m_speed(original_speed_setting())
	, m_empty_skip_count(0)
	, m_frameskip_level(machine.options().frameskip())
	, m_frameskip_counter(0)
	, m_frameskip_adjust(0)
	, m_skipping_this_frame(false)
	, m_average_oversleep(0)
	, m_snap_target(nullptr)
	, m_snap_native(true)
	, m_snap_width(0)
	, m_snap_height(0)
	, m_timecode_enabled(false)
	, m_timecode_write(false)
	, m_timecode_text("")
	, m_timecode_start(attotime::zero)
	, m_timecode_total(attotime::zero)
{
	// request a callback upon exiting
	machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(&video_manager::exit, this));
	machine.save().register_postload(save_prepost_delegate(FUNC(video_manager::postload), this));

	// extract initial execution state from global configuration settings
	update_refresh_speed();

	const unsigned screen_count(screen_device_iterator(machine.root_device()).count());
	const bool no_screens(!screen_count);

	// create a render target for snapshots
	const char *viewname = machine.options().snap_view();
	m_snap_native = !no_screens && (viewname[0] == 0 || strcmp(viewname, "native") == 0);

	if (m_snap_native)
	{
		// the native target is hard-coded to our internal layout and has all options disabled
		util::xml::file::ptr const root(util::xml::file::create());
		if (!root)
			throw emu_fatalerror("Couldn't create XML document??");
		util::xml::data_node *const layoutnode(root->add_child("mamelayout", nullptr));
		if (!layoutnode)
			throw emu_fatalerror("Couldn't create XML node??");
		layoutnode->set_attribute_int("version", 2);

		for (unsigned i = 0; screen_count > i; ++i)
		{
			util::xml::data_node *const viewnode(layoutnode->add_child("view", nullptr));
			if (!viewnode)
				throw emu_fatalerror("Couldn't create XML node??");
			viewnode->set_attribute("name", util::xml::normalize_string(util::string_format("s%1$u", i).c_str()));
			util::xml::data_node *const screennode(viewnode->add_child("screen", nullptr));
			if (!screennode)
				throw emu_fatalerror("Couldn't create XML node??");
			screennode->set_attribute_int("index", i);
			util::xml::data_node *const boundsnode(screennode->add_child("bounds", nullptr));
			if (!boundsnode)
				throw emu_fatalerror("Couldn't create XML node??");
			boundsnode->set_attribute_int("left", 0);
			boundsnode->set_attribute_int("top", 0);
			boundsnode->set_attribute_int("right", 1);
			boundsnode->set_attribute_int("bottom", 1);
		}

		m_snap_target = machine.render().target_alloc(*root, RENDER_CREATE_SINGLE_FILE | RENDER_CREATE_HIDDEN);
		m_snap_target->set_backdrops_enabled(false);
		m_snap_target->set_overlays_enabled(false);
		m_snap_target->set_bezels_enabled(false);
		m_snap_target->set_cpanels_enabled(false);
		m_snap_target->set_marquees_enabled(false);
		m_snap_target->set_screen_overlay_enabled(false);
		m_snap_target->set_zoom_to_screen(false);
	}
	else
	{
		// otherwise, non-default targets select the specified view and turn off effects
		m_snap_target = machine.render().target_alloc(nullptr, RENDER_CREATE_HIDDEN);
		m_snap_target->set_view(m_snap_target->configured_view(viewname, 0, 1));
		m_snap_target->set_screen_overlay_enabled(false);
	}

	// extract snap resolution if present
	if (sscanf(machine.options().snap_size(), "%dx%d", &m_snap_width, &m_snap_height) != 2)
		m_snap_width = m_snap_height = 0;

	// start recording movie if specified
	const char *filename = machine.options().mng_write();
	if (filename[0] != 0)
		begin_recording(filename, MF_MNG);

	filename = machine.options().avi_write();
	if (filename[0] != 0)
		begin_recording(filename, MF_AVI);

	// if no screens, create a periodic timer to drive updates
	if (no_screens)
	{
		m_screenless_frame_timer = machine.scheduler().timer_alloc(timer_expired_delegate(FUNC(video_manager::screenless_update_callback), this));
		m_screenless_frame_timer->adjust(screen_device::DEFAULT_FRAME_PERIOD, 0, screen_device::DEFAULT_FRAME_PERIOD);
		machine.output().set_notifier(nullptr, video_notifier_callback, this);
	}
}
Example #2
0
void sdl_window_info::update()
{
	osd_ticks_t     event_wait_ticks;

	// adjust the cursor state
	//sdlwindow_update_cursor_state(machine, window);

	update_cursor_state();

	// if we're visible and running and not in the middle of a resize, draw
	if (m_target != nullptr)
	{
		int tempwidth, tempheight;

		// see if the games video mode has changed
		m_target->compute_minimum_size(tempwidth, tempheight);
		if (osd_dim(tempwidth, tempheight) != m_minimum_dim)
		{
			m_minimum_dim = osd_dim(tempwidth, tempheight);

			if (!this->m_fullscreen)
			{
				//Don't resize window without user interaction;
				//window_resize(blitwidth, blitheight);
			}
			else if (video_config.switchres)
			{
				osd_dim tmp = this->pick_best_mode();
				resize(tmp.width(), tmp.height());
			}
		}

		if (video_config.waitvsync && video_config.syncrefresh)
			event_wait_ticks = osd_ticks_per_second(); // block at most a second
		else
			event_wait_ticks = 0;

		if (m_rendered_event.wait(event_wait_ticks))
		{
			const int update = 1;

			// ensure the target bounds are up-to-date, and then get the primitives

			render_primitive_list &primlist = *renderer().get_primitives();

			// and redraw now

			// Some configurations require events to be polled in the worker thread
			downcast< sdl_osd_interface& >(machine().osd()).process_events_buf();

			// Check whether window has vector screens

			{
				const screen_device *screen = screen_device_iterator(machine().root_device()).byindex(m_index);
				if ((screen != nullptr) && (screen->screen_type() == SCREEN_TYPE_VECTOR))
					renderer().set_flags(osd_renderer::FLAG_HAS_VECTOR_SCREEN);
				else
					renderer().clear_flags(osd_renderer::FLAG_HAS_VECTOR_SCREEN);
			}

			m_primlist = &primlist;

			// if no bitmap, just fill
			if (m_primlist == nullptr)
			{
			}
			// otherwise, render with our drawing system
			else
			{
				if( video_config.perftest )
					measure_fps(update);
				else
					renderer().draw(update);
			}

			/* all done, ready for next */
			m_rendered_event.set();
		}
	}
}
Example #3
0
void video_manager::record_frame()
{
	// ignore if nothing to do
	if (!is_recording())
		return;

	// start the profiler and get the current time
	g_profiler.start(PROFILER_MOVIE_REC);
	attotime curtime = machine().time();

	screen_device_iterator device_iterator = screen_device_iterator(machine().root_device());
	screen_device_iterator::auto_iterator iter = device_iterator.begin();

	for (uint32_t index = 0; index < (std::max)(m_mngs.size(), m_avis.size()); index++, iter++)
	{
		// create the bitmap
		create_snapshot_bitmap(iter.current());

		// handle an AVI recording
		if ((index < m_avis.size()) && m_avis[index].m_avi_file)
		{
			avi_info_t &avi_info = m_avis[index];

			// loop until we hit the right time
			while (avi_info.m_avi_next_frame_time <= curtime)
			{
				// write the next frame
				avi_file::error avierr = avi_info.m_avi_file->append_video_frame(m_snap_bitmap);
				if (avierr != avi_file::error::NONE)
				{
					g_profiler.stop(); // FIXME: double exit if this happens?
					end_recording_avi(index);
					break;
				}

				// advance time
				avi_info.m_avi_next_frame_time += avi_info.m_avi_frame_period;
				avi_info.m_avi_frame++;
			}
		}

		// handle a MNG recording
		if ((index < m_mngs.size()) && m_mngs[index].m_mng_file)
		{
			mng_info_t &mng_info = m_mngs[index];

			// loop until we hit the right time
			while (mng_info.m_mng_next_frame_time <= curtime)
			{
				// set up the text fields in the movie info
				png_info pnginfo;
				if (mng_info.m_mng_frame == 0)
				{
					std::string text1 = std::string(emulator_info::get_appname()).append(" ").append(emulator_info::get_build_version());
					std::string text2 = std::string(machine().system().manufacturer).append(" ").append(machine().system().type.fullname());
					pnginfo.add_text("Software", text1.c_str());
					pnginfo.add_text("System", text2.c_str());
				}

				// write the next frame
				screen_device *screen = iter.current();
				const rgb_t *palette = (screen != nullptr && screen->has_palette()) ? screen->palette().palette()->entry_list_adjusted() : nullptr;
				int entries = (screen != nullptr && screen->has_palette()) ? screen->palette().entries() : 0;
				png_error error = mng_capture_frame(*mng_info.m_mng_file, pnginfo, m_snap_bitmap, entries, palette);
				if (error != PNGERR_NONE)
				{
					g_profiler.stop(); // FIXME: double exit if this happens?
					end_recording_mng(index);
					break;
				}

				// advance time
				mng_info.m_mng_next_frame_time += mng_info.m_mng_frame_period;
				mng_info.m_mng_frame++;
			}
		}

		if (!m_snap_native)
		{
			break;
		}
	}

	g_profiler.stop();
}