From 497a8e9971d935be4c3d75cbebf862b645bc02a5 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Mon, 14 Sep 2020 15:46:35 +0200 Subject: Try vsync, fallback to fps limit if vsync fails --- src/QuickMedia.cpp | 124 +++++++++++++++++++++++++++++++++++++++++++---------- src/Vsync.cpp | 20 --------- 2 files changed, 101 insertions(+), 43 deletions(-) delete mode 100644 src/Vsync.cpp (limited to 'src') diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index 691357f..051fdc7 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -13,7 +13,6 @@ #include "../include/GoogleCaptcha.hpp" #include "../include/Notification.hpp" #include "../include/ImageViewer.hpp" -#include "../include/Vsync.hpp" #include #include @@ -28,6 +27,8 @@ #include #include #include +#include +#include static const sf::Color back_color(34, 34, 34); static const int DOUBLE_CLICK_TIME = 500; @@ -65,6 +66,79 @@ static int get_monitor_max_hz(Display *display) { return 60; } +static bool has_gl_ext(Display *disp, const char *ext) { + const char *extensions = glXQueryExtensionsString(disp, DefaultScreen(disp)); + if(!extensions) + return false; + + int ext_len = strlen(ext); + while(true) { + const char *loc = strstr(extensions, ext); + if(!loc) + return false; + + const char *terminator = loc + ext_len; + if((loc == extensions || *(loc - 1) == ' ') && (*terminator == ' ' || *terminator == '\0')) + return true; + + extensions = terminator; + } +} + +static PFNGLXSWAPINTERVALMESAPROC glXSwapIntervalMESA = nullptr; +static PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI = nullptr; +static PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT = nullptr; +static bool vsync_loaded = false; +static bool vsync_set = false; + +static bool test_vsync(Display *disp, Window window) { + unsigned int swap = 0; + glXQueryDrawable(disp, window, GLX_SWAP_INTERVAL_EXT, &swap); + printf("The swap interval is %u\n", swap); + return swap == 1; +} + +static bool enable_vsync(Display *disp, Window window) { + if(vsync_loaded) { + if(glXSwapIntervalMESA) + return glXSwapIntervalMESA(1) == 0; + if(glXSwapIntervalSGI) + return glXSwapIntervalSGI(1) == 0; + if(glXSwapIntervalEXT) { + glXSwapIntervalEXT(disp, window, 1); + return true; + } + return false; + } + vsync_loaded = true; + + if(has_gl_ext(disp, "GLX_MESA_swap_control")) { + fprintf(stderr, "vsync method: GLX_MESA_swap_control\n"); + glXSwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC)glXGetProcAddress((const GLubyte*)"glXSwapIntervalMESA"); + if(glXSwapIntervalMESA && glXSwapIntervalMESA(1) == 0 && test_vsync(disp, window)) + return true; + } + + if(has_gl_ext(disp, "GLX_SGI_swap_control")) { + fprintf(stderr, "vsync method: GLX_SGI_swap_control\n"); + glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddress((const GLubyte*)"glXSwapIntervalSGI"); + if(glXSwapIntervalSGI && glXSwapIntervalSGI(1) == 0 && test_vsync(disp, window)) + return true; + } + + if(has_gl_ext(disp, "GLX_EXT_swap_control")) { + fprintf(stderr, "vsync method: GLX_EXT_swap_control\n"); + glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddress((const GLubyte*)"glXSwapIntervalEXT"); + if(glXSwapIntervalEXT) { + glXSwapIntervalEXT(disp, window, 1); + return test_vsync(disp, window); + } + } + + fprintf(stderr, "vsync method: none\n"); + return false; +} + namespace QuickMedia { Program::Program() : disp(nullptr), @@ -84,7 +158,6 @@ namespace QuickMedia { resources_root = "/usr/share/quickmedia/"; } - window.setVerticalSyncEnabled(false); if(!font.loadFromFile(resources_root + "fonts/Lato-Regular.ttf")) { fprintf(stderr, "Failed to load font: Lato-Regular.ttf\n"); abort(); @@ -106,7 +179,14 @@ namespace QuickMedia { XSetErrorHandler(x_error_handler); XSetIOErrorHandler(x_io_error_handler); + window.setFramerateLimit(0); monitor_hz = get_monitor_max_hz(disp); + if(enable_vsync(disp, window.getSystemHandle())) { + vsync_set = true; + } else { + fprintf(stderr, "Failed to enable vsync, fallback to frame limiting\n"); + window.setFramerateLimit(monitor_hz); + } fprintf(stderr, "Monitor hz: %d\n", monitor_hz); } @@ -271,7 +351,10 @@ namespace QuickMedia { window.setFramerateLimit(4); image_page(); body->filter_search_fuzzy(""); - window.setFramerateLimit(0); + if(vsync_set) + window.setFramerateLimit(0); + else + window.setFramerateLimit(monitor_hz); window.setKeyRepeatEnabled(true); break; } @@ -791,7 +874,6 @@ namespace QuickMedia { sf::RectangleShape tab_drop_shadow; tab_drop_shadow.setFillColor(sf::Color(23, 25, 27)); - VSync vsync(monitor_hz); //sf::Clock tt; //int fps = 0; while (current_page == Page::SEARCH_SUGGESTION) { @@ -901,14 +983,14 @@ namespace QuickMedia { window.draw(tab_drop_shadow); } search_bar->draw(window, false); - vsync.display(window); // fps++; - // if(tt.getElapsedTime().asSeconds() >= 1.0f) { + // if(tt.getElapsedTime().asMilliseconds() >= 1000) { // fprintf(stderr, "fps: %d\n", fps); // fps = 0; // tt.restart(); // } + window.display(); } search_bar->onTextBeginTypingCallback = nullptr; @@ -1129,7 +1211,11 @@ namespace QuickMedia { related_media_window_size.x = window_size.x * RELATED_MEDIA_WINDOW_WIDTH; related_media_window_size.y = window_size.y; related_media_window = std::make_unique(sf::VideoMode(related_media_window_size.x, related_media_window_size.y), "", 0); - related_media_window->setVerticalSyncEnabled(false); + related_media_window->setFramerateLimit(0); + if(!enable_vsync(disp, related_media_window->getSystemHandle())) { + fprintf(stderr, "Failed to enable vsync, fallback to frame limiting\n"); + related_media_window->setFramerateLimit(monitor_hz); + } related_media_window->setVisible(false); XReparentWindow(disp, related_media_window->getSystemHandle(), video_player_window, window_size.x - related_media_window_size.x, 0); } @@ -1251,7 +1337,6 @@ namespace QuickMedia { bool is_youtube = current_plugin->name == "youtube"; - VSync vsync(monitor_hz); while (current_page == Page::VIDEO_CONTENT) { while (window.pollEvent(event)) { base_event_handler(event, previous_page, true, false, false); @@ -1361,7 +1446,7 @@ namespace QuickMedia { related_videos_text.setPosition(body_pos.x, 10.0f); related_media_window->draw(related_videos_text); related_media_body->draw(*related_media_window, body_pos, body_size); - vsync.display(*related_media_window); + related_media_window->display(); continue; } @@ -1462,7 +1547,6 @@ namespace QuickMedia { bool redraw = true; sf::Event event; - VSync vsync(monitor_hz); while (current_page == Page::EPISODE_LIST) { while (window.pollEvent(event)) { base_event_handler(event, Page::SEARCH_SUGGESTION); @@ -1492,7 +1576,7 @@ namespace QuickMedia { window.clear(back_color); body->draw(window, body_pos, body_size, json_chapters); search_bar->draw(window); - vsync.display(window); + window.display(); } } @@ -1703,7 +1787,6 @@ namespace QuickMedia { sf::Clock check_downloaded_timer; const sf::Int32 check_downloaded_timeout_ms = 500; - VSync vsync(4); // TODO: Show to user if a certain page is missing (by checking page name (number) and checking if some are skipped) while (current_page == Page::IMAGES) { while(window.pollEvent(event)) { @@ -1804,7 +1887,7 @@ namespace QuickMedia { window.draw(chapter_text); } - vsync.display(window); + window.display(); } } @@ -1849,7 +1932,6 @@ namespace QuickMedia { show_notification("Manga progress", "Failed to save manga progress", Urgency::CRITICAL); } - VSync vsync(monitor_hz); while(current_page == Page::IMAGES_CONTINUOUS) { window.clear(back_color); ImageViewerAction action = image_viewer.draw(window); @@ -1864,7 +1946,7 @@ namespace QuickMedia { current_page = Page::IMAGES; break; } - vsync.display(window); + window.display(); int focused_page = image_viewer.get_focused_page(); image_index = focused_page - 1; @@ -1908,7 +1990,6 @@ namespace QuickMedia { bool redraw = true; sf::Event event; - VSync vsync(monitor_hz); while (current_page == Page::CONTENT_LIST) { while (window.pollEvent(event)) { base_event_handler(event, Page::SEARCH_SUGGESTION); @@ -1928,7 +2009,7 @@ namespace QuickMedia { window.clear(back_color); body->draw(window, body_pos, body_size); search_bar->draw(window); - vsync.display(window); + window.display(); } } @@ -1958,7 +2039,6 @@ namespace QuickMedia { bool redraw = true; sf::Event event; - VSync vsync(monitor_hz); while (current_page == Page::CONTENT_DETAILS) { while (window.pollEvent(event)) { base_event_handler(event, Page::CONTENT_LIST); @@ -1977,7 +2057,7 @@ namespace QuickMedia { window.clear(back_color); body->draw(window, body_pos, body_size); search_bar->draw(window); - vsync.display(window); + window.display(); } } @@ -2012,7 +2092,6 @@ namespace QuickMedia { bool redraw = true; sf::Event event; - VSync vsync(monitor_hz); while (current_page == Page::IMAGE_BOARD_THREAD_LIST) { while (window.pollEvent(event)) { base_event_handler(event, Page::SEARCH_SUGGESTION); @@ -2031,7 +2110,7 @@ namespace QuickMedia { window.clear(back_color); body->draw(window, body_pos, body_size); search_bar->draw(window); - vsync.display(window); + window.display(); } } @@ -2196,7 +2275,6 @@ namespace QuickMedia { std::stack comment_navigation_stack; - VSync vsync(monitor_hz); while (current_page == Page::IMAGE_BOARD_THREAD) { while (window.pollEvent(event)) { search_bar->on_event(event); @@ -2439,7 +2517,7 @@ namespace QuickMedia { body->draw(window, body_pos, body_size); search_bar->draw(window); } - vsync.display(window); + window.display(); } // TODO: Instead of waiting for them, kill them somehow diff --git a/src/Vsync.cpp b/src/Vsync.cpp deleted file mode 100644 index d46f9fa..0000000 --- a/src/Vsync.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "../include/Vsync.hpp" -#include -#include - -namespace QuickMedia { - VSync::VSync(int framerate) : target_frame_delta_micro(1000.0 / (double)framerate * 1000.0), overflow(0) { - - } - - void VSync::display(sf::RenderWindow &window) { - window.display(); - sf::Int64 sleep_time_micro = target_frame_delta_micro - timer.getElapsedTime().asMicroseconds(); - if(sleep_time_micro > 0) { - if(usleep(sleep_time_micro) != 0) { - fprintf(stderr, "failed to sleep!\n"); - } - } - timer.restart(); - } -} \ No newline at end of file -- cgit v1.2.3