aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/Vsync.hpp15
-rw-r--r--src/QuickMedia.cpp124
-rw-r--r--src/Vsync.cpp20
3 files changed, 101 insertions, 58 deletions
diff --git a/include/Vsync.hpp b/include/Vsync.hpp
deleted file mode 100644
index 387d2b5..0000000
--- a/include/Vsync.hpp
+++ /dev/null
@@ -1,15 +0,0 @@
-#pragma once
-
-#include <SFML/Graphics/RenderWindow.hpp>
-
-namespace QuickMedia {
- class VSync {
- public:
- VSync(int framerate);
- void display(sf::RenderWindow &window);
- private:
- sf::Int64 target_frame_delta_micro;
- sf::Int64 overflow;
- sf::Clock timer;
- };
-} \ No newline at end of file
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 <cppcodec/base64_rfc4648.hpp>
#include <SFML/Graphics/RectangleShape.hpp>
@@ -28,6 +27,8 @@
#include <signal.h>
#include <X11/keysym.h>
#include <X11/extensions/Xrandr.h>
+#include <SFML/OpenGL.hpp>
+#include <GL/glx.h>
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::RenderWindow>(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<int> 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 <time.h>
-#include <unistd.h>
-
-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