Beispiel #1
0
static void ui_message_update(struct advance_ui_context* context, adv_bitmap* dst, struct ui_color_set* color)
{
	if (context->state.ui_message_stop_time < advance_timer()) {
		context->state.ui_message_flag = 0;
	}

	ui_messagebox_center(context, dst, dst->size_x / 2, dst->size_y / 2, context->state.ui_message_buffer, context->state.ui_message_buffer + strlen(context->state.ui_message_buffer), color->ui_f, color->ui_b, color->ui_alpha, color->def);
}
Beispiel #2
0
static double video_frame_wait(double current, double expected)
{
	while (current < expected) {
		double diff = expected - current;

		target_usleep(diff * 1E6);

		current = advance_timer();
	}

	return current;
}
Beispiel #3
0
static void video_frame_sync_free(struct advance_video_context* context)
{
	double current;

	current = advance_timer();

	if (context->state.sync_warming_up_flag) {
		context->state.sync_pivot = 0;
		context->state.sync_last = current;
		context->state.sync_skip_counter = 0;

		context->state.sync_warming_up_flag = 0;

		log_debug(("advance:sync: free warming up\n"));
	} else {
		context->state.sync_last = current;

		log_debug(("advance:sync: free\n"));
	}
}
Beispiel #4
0
/**
 * Display a message.
 * This function cannot be called from the video thread.
 */
void advance_ui_message_va(struct advance_ui_context* context, const char* text, va_list arg)
{
	context->state.ui_message_flag = 1;
	context->state.ui_message_stop_time = advance_timer() + 2; /* 2 seconds */
	vsnprintf(context->state.ui_message_buffer, sizeof(context->state.ui_message_buffer), text, arg);
}
Beispiel #5
0
static void video_frame_sync(struct advance_video_context* context)
{
	double current;
	double expected;

	current = advance_timer();

	if (context->state.sync_warming_up_flag) {
		/* syncronize the first time */
		if (context->state.vsync_flag) {
			video_wait_vsync();
			current = advance_timer();
		}

		context->state.sync_pivot = 0;
		context->state.sync_last = current;
		context->state.sync_skip_counter = 0;

		context->state.sync_warming_up_flag = 0;

		log_debug(("advance:sync: throttle warming up\n"));
	} else {
		double time_before_sync, time_after_delay, time_after_sync;

		time_before_sync = current;

		expected = context->state.sync_last + context->state.skip_step * (1 + context->state.sync_skip_counter);
		context->state.sync_skip_counter = 0;

		/* take only a part of the error, this increase the stability */
		context->state.sync_pivot *= 0.99;

		/* adjust with the previous error */
		expected += context->state.sync_pivot;

		/* the vsync is used only if all the frames are displayed */
		if ((video_flags() & MODE_FLAGS_RETRACE_WAIT_SYNC) != 0
			&& context->state.vsync_flag
			&& context->state.skip_level_full == SYNC_MAX
		) {
			/* wait until the retrace is near (3% early), otherwise if the */
			/* mode has a double freq the retrace may be the wrong one. */
			double early = 0.03 / video_measured_vclock();

			if (current < expected - early) {
				current = video_frame_wait(current, expected - early);
				time_after_delay = current;

				if (current < expected) {
					double after;
					video_wait_vsync();
					after = advance_timer();
					
					if (after - current > 1.05 / (double)video_measured_vclock()) {
						log_std(("ERROR:emu:video: sync wait too long. %g instead of %g (max %g)\n", after - current, early, 1.0 / (double)video_measured_vclock()));
					} else if (after - current > 1.05 * early) {
						log_std(("WARNING:emu:video: sync wait too long. %g instead of %g (max %g)\n", after - current, early, 1.0 / (double)video_measured_vclock()));
					}
					
					/* if a sync complete correctly reset the error to 0 */
					/* in this case the vsync is used for the correct clocking */
					expected = after;
					
					current = after;
				} else {
					log_std(("ERROR:emu:video: sync delay too big\n"));
				}
			} else {
				log_std(("ERROR:emu:video: too late for a video sync\n"));
				current = video_frame_wait(current, expected);
				time_after_delay = current;
			}
		} else {
			current = video_frame_wait(current, expected);
			time_after_delay = current;
		}

		time_after_sync = current;

		/* update the error state */
		context->state.sync_pivot = expected - current;

		if (fabs(context->state.sync_pivot) > context->state.skip_step / 50)
			log_std(("advance:sync: %.5f (err %6.1f%%) = %.5f + %.5f + %.5f < %.5f (compute + sleep + sync < max)\n", current - context->state.sync_last, context->state.sync_pivot * 100 / context->state.skip_step, time_before_sync - context->state.sync_last, time_after_delay - time_before_sync, time_after_sync - time_after_delay, context->state.skip_step));

		if (context->state.sync_pivot < - context->state.skip_step * 16) {
			/* if the error is too big (negative) the delay is unrecoverable */
			/* generally it happen with a virtual terminal switch */
			/* the best solution is to restart the sync computation */
			advance_video_update_skip(context);
			advance_video_update_sync(context);
		}

		context->state.sync_last = current;
	}
}