static int test_vbe(int x, int y, vbe_video_mode* mode) { char buffer[256]; struct vga_info info; struct vga_regs regs; adv_crtc crtc; draw_test_default(); snprintf(buffer, sizeof(buffer), "vbe %s 0x%x %dx%dx%d [%dx%d]", index_name(video_index()), mode->mode, video_size_x(), video_size_y(), video_bits_per_pixel(), video_virtual_x(), video_virtual_y()); draw_string(x, y, buffer, DRAW_COLOR_WHITE); ++y; ++y; vga_mode_get(®s); vga_regs_info_get(®s, &info); if (crtc_import(&crtc, &info, video_size_x(), video_size_y(), video_measured_vclock())==0) { ++y; y = test_crtc(x, y, &crtc, 0, 1, 0); } ++y; y = test_default_command(x, y); return y; }
/** * Update the sync state. * Enables or disables the video vertical sync from the game framerate * and the current speed state. */ void advance_video_update_sync(struct advance_video_context* context) { double rate = video_measured_vclock(); double reference = context->state.game_fps; context->state.sync_warming_up_flag = 1; if (rate > 10 && rate < 300) { context->state.mode_vclock = video_rate_scale_down(rate, reference); context->state.vsync_flag = context->config.vsync_flag; } else { /* out of range, surely NOT supported */ context->state.mode_vclock = reference; context->state.vsync_flag = 0; } if (context->state.vsync_flag) { /* disable if no throttling */ if (!context->state.sync_throttle_flag) { log_std(("emu:video: vsync disabled because throttle disactive\n")); context->state.vsync_flag = 0; } /* disable if turbo active */ if (context->state.turbo_flag) { log_std(("emu:video: vsync disabled because turbo active\n")); context->state.vsync_flag = 0; } /* disable if fastest active */ if (context->state.fastest_flag) { log_std(("emu:video: vsync disabled because fastest active\n")); context->state.vsync_flag = 0; } /* disable if measure active */ if (context->state.measure_flag) { log_std(("emu:video: vsync disabled because measure active\n")); context->state.vsync_flag = 0; } /* disable the vsync flag if the frame rate is wrong */ if (context->state.mode_vclock < reference * 0.97 || context->state.mode_vclock > reference * 1.03) { log_std(("emu:video: vsync disabled because the vclock is too different %g %g\n", reference, context->state.mode_vclock)); context->state.vsync_flag = 0; } } }
int osd2_video_menu(int selected, unsigned input) { struct advance_video_context* video_context = &CONTEXT.video; struct advance_global_context* global_context = &CONTEXT.global; struct advance_ui_context* ui_context = &CONTEXT.ui; struct ui_menu menu; unsigned mac; int resolution_index; int stretch_index; int vsync_index; int combine_index; int effect_index; int save_game_index; int save_resolution_index; int save_resolutionclock_index; int pipeline_index; int magnify_index; int index_index; int smp_index; int crash_index; int exit_index; char buffer[128]; char freq[32]; const char* text = 0; const char* option = 0; /* the menu data is not duplicated for the thread, so we have to wait for its completion */ advance_video_thread_wait(video_context); if (selected >= 1) selected = selected - 1; else selected = 0; if (video_context->state.menu_sub_flag) { int ret = 0; switch (video_context->state.menu_sub_flag) { case 1: ret = video_mode_menu(video_context, ui_context, video_context->state.menu_sub_selected, input); break; case 2: ret = video_pipeline_menu(video_context, ui_context, video_context->state.menu_sub_selected, input); break; } switch (ret) { case -1: return -1; /* hide interface */ case 0: video_context->state.menu_sub_flag = 0; video_context->state.menu_sub_selected = 1; break; /* close submenu */ default: video_context->state.menu_sub_selected = ret; break; } return selected + 1; } advance_ui_menu_init(&menu); advance_ui_menu_title_insert(&menu, "Video Menu"); snprintf(buffer, sizeof(buffer), "%dx%dx%d %.1f/%.1f/%.1f", video_size_x(), video_size_y(), video_bits_per_pixel(), (double)crtc_pclock_get(&video_context->state.crtc_effective) / 1E6, (double)crtc_hclock_get(&video_context->state.crtc_effective) / 1E3, (double)crtc_vclock_get(&video_context->state.crtc_effective) ); advance_ui_menu_title_insert(&menu, buffer); resolution_index = advance_ui_menu_option_insert(&menu, "Mode...", video_context->config.resolution_buffer); if (!video_context->state.game_vector_flag) { if (strcmp(video_context->config.resolution_buffer, "auto") == 0) { switch (mode_current_magnify(video_context)) { default: case 1: text = "Magnify [1]"; break; case 2: text = "Magnify [2]"; break; case 3: text = "Magnify [3]"; break; case 4: text = "Magnify [4]"; break; } switch (video_context->config.magnify_factor) { default: case 0: option = "auto"; break; case 1: option = "1"; break; case 2: option = "2"; break; case 3: option = "3"; break; case 4: option = "4"; break; } magnify_index = advance_ui_menu_option_insert(&menu, text, option); } else { magnify_index = -1; } advance_ui_menu_title_insert(&menu, "Options"); switch (mode_current_stretch(video_context)) { case STRETCH_NONE: text = "Resize [no]"; break; case STRETCH_INTEGER_XY: text = "Resize [integer]"; break; case STRETCH_INTEGER_X_FRACTIONAL_Y: text = "Resize [mixed]"; break; case STRETCH_FRACTIONAL_XY: text = "Resize [fractional]"; break; } switch (video_context->config.stretch) { case STRETCH_NONE: option = "no"; break; case STRETCH_INTEGER_XY: option = "integer"; break; case STRETCH_INTEGER_X_FRACTIONAL_Y: option = "mixed"; break; case STRETCH_FRACTIONAL_XY: option = "fractional"; break; } stretch_index = advance_ui_menu_option_insert(&menu, text, option); } else { magnify_index = -1; advance_ui_menu_title_insert(&menu, "Options"); stretch_index = -1; } switch (video_index()) { case MODE_FLAGS_INDEX_PALETTE8: text = "Color [palette8]"; break; case MODE_FLAGS_INDEX_BGR8: text = "Color [bgr8]"; break; case MODE_FLAGS_INDEX_BGR15: text = "Color [bgr15]"; break; case MODE_FLAGS_INDEX_BGR16: text = "Color [bgr16]"; break; case MODE_FLAGS_INDEX_BGR32: text = "Color [bgr32]"; break; case MODE_FLAGS_INDEX_YUY2: text = "Color [yuy2]"; break; default: text = "Color [unknown]"; break; } switch (video_context->config.index) { case MODE_FLAGS_INDEX_NONE: option = "auto"; break; case MODE_FLAGS_INDEX_PALETTE8: option = "palette8"; break; case MODE_FLAGS_INDEX_BGR8: option = "bgr8"; break; case MODE_FLAGS_INDEX_BGR15: option = "bgr15"; break; case MODE_FLAGS_INDEX_BGR16: option = "bgr16"; break; case MODE_FLAGS_INDEX_BGR32: option = "bgr32"; break; case MODE_FLAGS_INDEX_YUY2: option = "yuy2"; break; default: option = "unknown"; break; } index_index = advance_ui_menu_option_insert(&menu, text, option); switch (video_context->state.combine) { case COMBINE_NONE: text = "Resize Effect [no]"; break; case COMBINE_MAXMIN: text = "Resize Effect [max]"; break; case COMBINE_MEAN: text = "Resize Effect [mean]"; break; case COMBINE_FILTER: text = "Resize Effect [filter]"; break; case COMBINE_SCALEX: text = "Resize Effect [scalex]"; break; case COMBINE_SCALEK: text = "Resize Effect [scalek]"; break; case COMBINE_HQ: text = "Resize Effect [hq]"; break; case COMBINE_XBR: text = "Resize Effect [xbr]"; break; } switch (video_context->config.combine) { case COMBINE_AUTO: option = "auto"; break; case COMBINE_NONE: option = "no"; break; case COMBINE_MAXMIN: option = "max"; break; case COMBINE_MEAN: option = "mean"; break; case COMBINE_FILTER: option = "filter"; break; case COMBINE_SCALEX: option = "scalex"; break; case COMBINE_SCALEK: option = "scalek"; break; case COMBINE_HQ: option = "hq"; break; case COMBINE_XBR: option = "xbr"; break; } combine_index = advance_ui_menu_option_insert(&menu, text, option); switch (video_context->state.rgb_effect) { case EFFECT_NONE: text = "Rgb Effect [no]"; break; case EFFECT_RGB_TRIAD3PIX: text = "Rgb Effect [triad3dot]"; break; case EFFECT_RGB_TRIAD6PIX: text = "Rgb Effect [triad6dot]"; break; case EFFECT_RGB_TRIAD16PIX: text = "Rgb Effect [triad16dot]"; break; case EFFECT_RGB_TRIADSTRONG3PIX: text = "Rgb Effect [triadstrong3dot]"; break; case EFFECT_RGB_TRIADSTRONG6PIX: text = "Rgb Effect [triadstrong6dot]"; break; case EFFECT_RGB_TRIADSTRONG16PIX: text = "Rgb Effect [triadstrong16dot]"; break; case EFFECT_RGB_SCANDOUBLEHORZ: text = "Rgb Effect [scan2horz]"; break; case EFFECT_RGB_SCANTRIPLEHORZ: text = "Rgb Effect [scan3horz]"; break; case EFFECT_RGB_SCANDOUBLEVERT: text = "Rgb Effect [scan2vert]"; break; case EFFECT_RGB_SCANTRIPLEVERT: text = "Rgb Effect [scan3vert]"; break; } switch (video_context->config.rgb_effect) { case EFFECT_NONE: option = "no"; break; case EFFECT_RGB_TRIAD3PIX: option = "triad3dot"; break; case EFFECT_RGB_TRIAD6PIX: option = "triad6dot"; break; case EFFECT_RGB_TRIAD16PIX: option = "triad16dot"; break; case EFFECT_RGB_TRIADSTRONG3PIX: option = "triadstrong3dot"; break; case EFFECT_RGB_TRIADSTRONG6PIX: option = "triadstrong6dot"; break; case EFFECT_RGB_TRIADSTRONG16PIX: option = "triadstrong16dot"; break; case EFFECT_RGB_SCANDOUBLEHORZ: option = "scan2horz"; break; case EFFECT_RGB_SCANTRIPLEHORZ: option = "scan3horz"; break; case EFFECT_RGB_SCANDOUBLEVERT: option = "scan2vert"; break; case EFFECT_RGB_SCANTRIPLEVERT: option = "scan3vert"; break; } effect_index = advance_ui_menu_option_insert(&menu, text, option); switch (video_context->state.vsync_flag) { case 0: text = "Vsync [no]"; break; case 1: snprintf(freq, sizeof(freq), "Vsync [%.1f]", video_measured_vclock()); text = freq; break; } switch (video_context->config.vsync_flag) { case 0: option = "no"; break; case 1: option = "yes"; break; } vsync_index = advance_ui_menu_option_insert(&menu, text, option); #ifdef USE_SMP switch (video_context->config.smp_flag) { case 0: text = "SMP [no]"; break; case 1: text = "SMP [yes]"; break; } switch (video_context->config.smp_flag) { case 0: option = "no"; break; case 1: option = "yes"; break; } smp_index = advance_ui_menu_option_insert(&menu, text, option); #else smp_index = -1; #endif pipeline_index = advance_ui_menu_text_insert(&menu, "Details..."); if (global_context->state.is_config_writable) { save_game_index = advance_ui_menu_text_insert(&menu, "Save for this game"); if (!video_context->state.game_vector_flag) { save_resolutionclock_index = advance_ui_menu_text_insert(&menu, "Save for this game size/freq"); } else { save_resolutionclock_index = -1; } if (video_context->state.game_vector_flag) text = "Save for all vector games"; else text = "Save for this game size"; save_resolution_index = advance_ui_menu_text_insert(&menu, text); } else { save_game_index = -1; save_resolution_index = -1; save_resolutionclock_index = -1; } if (video_context->config.crash_flag) { crash_index = advance_ui_menu_text_insert(&menu, "Crash"); } else { crash_index = -1; } exit_index = advance_ui_menu_text_insert(&menu, "Return to Main Menu"); mac = advance_ui_menu_done(&menu, ui_context, selected); if (input == OSD_INPUT_DOWN) { selected = (selected + 1) % mac; } if (input == OSD_INPUT_UP) { selected = (selected + mac - 1) % mac; } if (input == OSD_INPUT_SELECT) { if (selected == exit_index) { selected = -1; } else if (selected == resolution_index) { video_context->state.menu_sub_flag = 1; } else if (selected == pipeline_index) { video_context->state.menu_sub_flag = 2; } else if (selected == save_game_index) { advance_video_config_save(video_context, video_context->config.section_name_buffer); } else if (selected == save_resolution_index) { advance_video_config_save(video_context, video_context->config.section_resolution_buffer); } else if (selected == save_resolutionclock_index) { advance_video_config_save(video_context, video_context->config.section_resolutionclock_buffer); } else if (selected == crash_index) { target_crash(); } } if (input == OSD_INPUT_RIGHT) { if (selected == combine_index) { struct advance_video_config_context config = video_context->config; switch (config.combine) { case COMBINE_AUTO: config.combine = COMBINE_NONE; break; case COMBINE_NONE: config.combine = COMBINE_MAXMIN; break; case COMBINE_MAXMIN: config.combine = COMBINE_MEAN; break; case COMBINE_MEAN: config.combine = COMBINE_FILTER; break; case COMBINE_FILTER: config.combine = COMBINE_SCALEX; break; case COMBINE_SCALEX: config.combine = COMBINE_SCALEK; break; case COMBINE_SCALEK: config.combine = COMBINE_HQ; break; case COMBINE_HQ: config.combine = COMBINE_XBR; break; case COMBINE_XBR: config.combine = COMBINE_AUTO; break; } advance_video_reconfigure(video_context, &config); } else if (selected == effect_index) { struct advance_video_config_context config = video_context->config; switch (config.rgb_effect) { case EFFECT_NONE: config.rgb_effect = EFFECT_RGB_TRIAD3PIX; break; case EFFECT_RGB_TRIAD3PIX: config.rgb_effect = EFFECT_RGB_TRIADSTRONG3PIX; break; case EFFECT_RGB_TRIADSTRONG3PIX: config.rgb_effect = EFFECT_RGB_TRIAD6PIX; break; case EFFECT_RGB_TRIAD6PIX: config.rgb_effect = EFFECT_RGB_TRIADSTRONG6PIX; break; case EFFECT_RGB_TRIADSTRONG6PIX: config.rgb_effect = EFFECT_RGB_TRIAD16PIX; break; case EFFECT_RGB_TRIAD16PIX: config.rgb_effect = EFFECT_RGB_TRIADSTRONG16PIX; break; case EFFECT_RGB_TRIADSTRONG16PIX: config.rgb_effect = EFFECT_RGB_SCANDOUBLEHORZ; break; case EFFECT_RGB_SCANDOUBLEHORZ: config.rgb_effect = EFFECT_RGB_SCANTRIPLEHORZ; break; case EFFECT_RGB_SCANTRIPLEHORZ: config.rgb_effect = EFFECT_RGB_SCANDOUBLEVERT; break; case EFFECT_RGB_SCANDOUBLEVERT: config.rgb_effect = EFFECT_RGB_SCANTRIPLEVERT; break; case EFFECT_RGB_SCANTRIPLEVERT: config.rgb_effect = EFFECT_NONE; break; } advance_video_reconfigure(video_context, &config); } else if (selected == vsync_index) { struct advance_video_config_context config = video_context->config; switch (config.vsync_flag) { case 0: config.vsync_flag = 1; break; case 1: config.vsync_flag = 0; break; } advance_video_reconfigure(video_context, &config); } else if (selected == smp_index) { struct advance_video_config_context config = video_context->config; switch (config.smp_flag) { case 0: config.smp_flag = 1; break; case 1: config.smp_flag = 0; break; } advance_video_reconfigure(video_context, &config); } else if (selected == magnify_index) { struct advance_video_config_context config = video_context->config; if (config.magnify_factor == 4) config.magnify_factor = 0; else config.magnify_factor += 1; advance_video_reconfigure(video_context, &config); } else if (selected == index_index) { struct advance_video_config_context config = video_context->config; switch (config.index) { case MODE_FLAGS_INDEX_NONE: config.index = MODE_FLAGS_INDEX_PALETTE8; break; case MODE_FLAGS_INDEX_PALETTE8: config.index = MODE_FLAGS_INDEX_BGR8; break; case MODE_FLAGS_INDEX_BGR8: config.index = MODE_FLAGS_INDEX_BGR15; break; case MODE_FLAGS_INDEX_BGR15: config.index = MODE_FLAGS_INDEX_BGR16; break; case MODE_FLAGS_INDEX_BGR16: config.index = MODE_FLAGS_INDEX_BGR32; break; case MODE_FLAGS_INDEX_BGR32: config.index = MODE_FLAGS_INDEX_YUY2; break; case MODE_FLAGS_INDEX_YUY2: config.index = MODE_FLAGS_INDEX_NONE; break; } advance_video_reconfigure(video_context, &config); } else if (selected == stretch_index) { struct advance_video_config_context config = video_context->config; switch (config.stretch) { case STRETCH_NONE: config.stretch = STRETCH_FRACTIONAL_XY; break; case STRETCH_INTEGER_XY: config.stretch = STRETCH_NONE; break; case STRETCH_INTEGER_X_FRACTIONAL_Y: config.stretch = STRETCH_INTEGER_XY; break; case STRETCH_FRACTIONAL_XY: config.stretch = STRETCH_INTEGER_X_FRACTIONAL_Y; break; } advance_video_reconfigure(video_context, &config); } } if (input == OSD_INPUT_LEFT) { if (selected == combine_index) { struct advance_video_config_context config = video_context->config; switch (config.combine) { case COMBINE_AUTO: config.combine = COMBINE_XBR; break; case COMBINE_NONE: config.combine = COMBINE_AUTO; break; case COMBINE_MAXMIN: config.combine = COMBINE_NONE; break; case COMBINE_MEAN: config.combine = COMBINE_MAXMIN; break; case COMBINE_FILTER: config.combine = COMBINE_MEAN; break; case COMBINE_SCALEX: config.combine = COMBINE_FILTER; break; case COMBINE_SCALEK: config.combine = COMBINE_SCALEX; break; case COMBINE_HQ: config.combine = COMBINE_SCALEK; break; case COMBINE_XBR: config.combine = COMBINE_HQ; break; } advance_video_reconfigure(video_context, &config); } else if (selected == effect_index) { struct advance_video_config_context config = video_context->config; switch (config.rgb_effect) { case EFFECT_NONE: config.rgb_effect = EFFECT_RGB_SCANTRIPLEVERT; break; case EFFECT_RGB_TRIAD3PIX: config.rgb_effect = EFFECT_NONE; break; case EFFECT_RGB_TRIADSTRONG3PIX: config.rgb_effect = EFFECT_RGB_TRIAD3PIX; break; case EFFECT_RGB_TRIAD6PIX: config.rgb_effect = EFFECT_RGB_TRIADSTRONG3PIX; break; case EFFECT_RGB_TRIADSTRONG6PIX: config.rgb_effect = EFFECT_RGB_TRIAD6PIX; break; case EFFECT_RGB_TRIAD16PIX: config.rgb_effect = EFFECT_RGB_TRIADSTRONG6PIX; break; case EFFECT_RGB_TRIADSTRONG16PIX: config.rgb_effect = EFFECT_RGB_TRIAD16PIX; break; case EFFECT_RGB_SCANDOUBLEHORZ: config.rgb_effect = EFFECT_RGB_TRIADSTRONG16PIX; break; case EFFECT_RGB_SCANTRIPLEHORZ: config.rgb_effect = EFFECT_RGB_SCANDOUBLEHORZ; break; case EFFECT_RGB_SCANDOUBLEVERT: config.rgb_effect = EFFECT_RGB_SCANTRIPLEHORZ; break; case EFFECT_RGB_SCANTRIPLEVERT: config.rgb_effect = EFFECT_RGB_SCANDOUBLEVERT; break; } advance_video_reconfigure(video_context, &config); } else if (selected == vsync_index) { struct advance_video_config_context config = video_context->config; switch (config.vsync_flag) { case 0: config.vsync_flag = 1; break; case 1: config.vsync_flag = 0; break; } advance_video_reconfigure(video_context, &config); } else if (selected == smp_index) { struct advance_video_config_context config = video_context->config; switch (config.smp_flag) { case 0: config.smp_flag = 1; break; case 1: config.smp_flag = 0; break; } advance_video_reconfigure(video_context, &config); } else if (selected == magnify_index) { struct advance_video_config_context config = video_context->config; if (config.magnify_factor == 0) config.magnify_factor = 4; else config.magnify_factor -= 1; advance_video_reconfigure(video_context, &config); } else if (selected == index_index) { struct advance_video_config_context config = video_context->config; switch (config.index) { case MODE_FLAGS_INDEX_NONE: config.index = MODE_FLAGS_INDEX_YUY2; break; case MODE_FLAGS_INDEX_PALETTE8: config.index = MODE_FLAGS_INDEX_NONE; break; case MODE_FLAGS_INDEX_BGR8: config.index = MODE_FLAGS_INDEX_PALETTE8; break; case MODE_FLAGS_INDEX_BGR15: config.index = MODE_FLAGS_INDEX_BGR8; break; case MODE_FLAGS_INDEX_BGR16: config.index = MODE_FLAGS_INDEX_BGR15; break; case MODE_FLAGS_INDEX_BGR32: config.index = MODE_FLAGS_INDEX_BGR16; break; case MODE_FLAGS_INDEX_YUY2: config.index = MODE_FLAGS_INDEX_BGR32; break; } advance_video_reconfigure(video_context, &config); } else if (selected == stretch_index) { struct advance_video_config_context config = video_context->config; switch (config.stretch) { case STRETCH_NONE: config.stretch = STRETCH_INTEGER_XY; break; case STRETCH_INTEGER_XY: config.stretch = STRETCH_INTEGER_X_FRACTIONAL_Y; break; case STRETCH_INTEGER_X_FRACTIONAL_Y: config.stretch = STRETCH_FRACTIONAL_XY; break; case STRETCH_FRACTIONAL_XY: config.stretch = STRETCH_NONE; break; } advance_video_reconfigure(video_context, &config); } } if (input == OSD_INPUT_CANCEL) selected = -1; if (input == OSD_INPUT_CONFIGURE) selected = -2; return selected + 1; }
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; } }
static int test_crtc(int x, int y, adv_crtc* crtc, int print_clock, int print_measured_clock, int print_key) { char buffer[256]; snprintf(buffer, sizeof(buffer), "Horz Vert"); draw_string(x, y, buffer, DRAW_COLOR_WHITE); ++y; if (print_clock) { snprintf(buffer, sizeof(buffer), "%4.1f %5.1f %sClock Requested [kHz Hz]", crtc_hclock_get(crtc) / 1E3, crtc_vclock_get(crtc), print_key ? " " : ""); draw_string(x, y, buffer, DRAW_COLOR_WHITE); ++y; } if (print_measured_clock) { snprintf(buffer, sizeof(buffer), " %5.1f %sClock Measured [Hz]", video_measured_vclock(), print_key ? " " : ""); draw_string(x, y, buffer, DRAW_COLOR_WHITE); ++y; } snprintf(buffer, sizeof(buffer), "%4d %4d %sDisplay End", crtc->hde, crtc->vde, print_key ? "[qa] " : ""); draw_string(x, y, buffer, DRAW_COLOR_WHITE); ++y; snprintf(buffer, sizeof(buffer), "%4d %4d %sRetrace Start", crtc->hrs, crtc->vrs, print_key ? "[ed] " : ""); draw_string(x, y, buffer, DRAW_COLOR_WHITE); ++y; if (!(crtc->hde<=crtc->hrs)) { snprintf(buffer, sizeof(buffer), "HDE<=HRS"); draw_string(x, y, buffer, DRAW_COLOR_RED); ++y; } if (!(crtc->vde<=crtc->vrs)) { snprintf(buffer, sizeof(buffer), "VDE<=VRS"); draw_string(x, y, buffer, DRAW_COLOR_RED); ++y; } snprintf(buffer, sizeof(buffer), "%4d %4d %sRetrace End", crtc->hre, crtc->vre, print_key ? "[rf] " : ""); draw_string(x, y, buffer, DRAW_COLOR_WHITE); ++y; if (!(crtc->hrs<crtc->hre)) { snprintf(buffer, sizeof(buffer), "HRS<HRE"); draw_string(x, y, buffer, DRAW_COLOR_RED); ++y; } if (!(crtc->vrs<crtc->vre)) { snprintf(buffer, sizeof(buffer), "VRE<VRE"); draw_string(x, y, buffer, DRAW_COLOR_RED); ++y; } snprintf(buffer, sizeof(buffer), "%4d %4d %sTotal", crtc->ht, crtc->vt, print_key ? "[yh] " : ""); draw_string(x, y, buffer, DRAW_COLOR_WHITE); ++y; if (!(crtc->hre<=crtc->ht)) { snprintf(buffer, sizeof(buffer), "HRE<=HT"); draw_string(x, y, buffer, DRAW_COLOR_RED); ++y; } if (!(crtc->vre<=crtc->vt)) { snprintf(buffer, sizeof(buffer), "VRE<=VT"); draw_string(x, y, buffer, DRAW_COLOR_RED); ++y; } snprintf(buffer, sizeof(buffer), " %c %c %sPolarization", crtc_is_nhsync(crtc) ? '-' : '+', crtc_is_nvsync(crtc) ? '-' : '+', print_key ? "[uj] " : ""); draw_string(x, y, buffer, DRAW_COLOR_WHITE); ++y; snprintf(buffer, sizeof(buffer), " %4s %sDoublescan", crtc_is_doublescan(crtc) ? "on" : "off", print_key ? "[x] " : ""); draw_string(x, y, buffer, DRAW_COLOR_WHITE); ++y; snprintf(buffer, sizeof(buffer), " %4s %sInterlaced", crtc_is_interlace(crtc) ? "on" : "off", print_key ? "[c] " : ""); draw_string(x, y, buffer, DRAW_COLOR_WHITE); ++y; if (print_clock) { snprintf(buffer, sizeof(buffer), "%4.2f %sPixelclock [MHz]", (double)crtc->pixelclock / 1E6, print_key ? "[v] " : ""); draw_string(x, y, buffer, DRAW_COLOR_WHITE); ++y; } if (print_key) { ++y; draw_string(x, y, "Q...U Inc horz (SHIFT dec)", DRAW_COLOR_WHITE); ++y; draw_string(x, y, "A...J Inc vert (SHIFT dec)", DRAW_COLOR_WHITE); ++y; draw_string(x, y, "I,K Inc horz/vert size (SHIFT dec)", DRAW_COLOR_WHITE); ++y; draw_string(x, y, "XCV Flip flag", DRAW_COLOR_WHITE); ++y; draw_string(x, y, "ARROWS Center", DRAW_COLOR_WHITE); ++y; } return y; }