diff --git a/core/rend/vulkan/vulkan_context.cpp b/core/rend/vulkan/vulkan_context.cpp index 2e79f11ea..74b3232b1 100644 --- a/core/rend/vulkan/vulkan_context.cpp +++ b/core/rend/vulkan/vulkan_context.cpp @@ -564,25 +564,24 @@ void VulkanContext::CreateSwapChain() // The FIFO present mode is guaranteed by the spec to be supported vk::PresentModeKHR swapchainPresentMode = vk::PresentModeKHR::eFifo; // Use FIFO on mobile, prefer Mailbox on desktop -#if HOST_CPU != CPU_ARM && HOST_CPU != CPU_ARM64 && !defined(__ANDROID__) for (auto& presentMode : physicalDevice.getSurfacePresentModesKHR(GetSurface())) { - if (presentMode == vk::PresentModeKHR::eMailbox && vendorID != VENDOR_ATI && vendorID != VENDOR_AMD) +#if HOST_CPU != CPU_ARM && HOST_CPU != CPU_ARM64 && !defined(__ANDROID__) + if (swapOnVSync && presentMode == vk::PresentModeKHR::eMailbox + && vendorID != VENDOR_ATI && vendorID != VENDOR_AMD) { INFO_LOG(RENDERER, "Using mailbox present mode"); swapchainPresentMode = vk::PresentModeKHR::eMailbox; break; } -#ifdef TEST_AUTOMATION - if (presentMode == vk::PresentModeKHR::eImmediate) +#endif + if (!swapOnVSync && presentMode == vk::PresentModeKHR::eImmediate) { INFO_LOG(RENDERER, "Using immediate present mode"); swapchainPresentMode = vk::PresentModeKHR::eImmediate; break; } -#endif } -#endif vk::SurfaceTransformFlagBitsKHR preTransform = (surfaceCapabilities.supportedTransforms & vk::SurfaceTransformFlagBitsKHR::eIdentity) ? vk::SurfaceTransformFlagBitsKHR::eIdentity : surfaceCapabilities.currentTransform; @@ -802,6 +801,13 @@ void VulkanContext::Present() noexcept } renderDone = false; } +#ifndef TEST_AUTOMATION + if (swapOnVSync == settings.input.fastForwardMode) + { + swapOnVSync = !settings.input.fastForwardMode; + resized = true; + } +#endif if (resized) try { CreateSwapChain(); diff --git a/core/rend/vulkan/vulkan_context.h b/core/rend/vulkan/vulkan_context.h index 75042373d..1d870d490 100644 --- a/core/rend/vulkan/vulkan_context.h +++ b/core/rend/vulkan/vulkan_context.h @@ -140,6 +140,11 @@ private: u32 width = 0; u32 height = 0; bool resized = false; +#ifndef TEST_AUTOMATION + bool swapOnVSync = true; +#else + bool swapOnVSync = false; +#endif vk::UniqueInstance instance; vk::PhysicalDevice physicalDevice; diff --git a/core/wsi/egl.cpp b/core/wsi/egl.cpp index 216cc62c6..9aede4ece 100644 --- a/core/wsi/egl.cpp +++ b/core/wsi/egl.cpp @@ -181,7 +181,12 @@ bool EGLGraphicsContext::Init() #ifdef TARGET_PANDORA fbdev = open("/dev/fb0", O_RDONLY); #else - eglSwapInterval(display, 1); +#ifndef TEST_AUTOMATION + swapOnVSync = true; +#else + swapOnVSync = false; +#endif + eglSwapInterval(display, (int)swapOnVSync); #endif PostInit(); @@ -215,12 +220,11 @@ void EGLGraphicsContext::Swap() { #ifdef TEST_AUTOMATION do_swap_automation(); -#endif -#if 0 && defined(TARGET_PANDORA) - if (fbdev >= 0) +#else + if (swapOnVSync == settings.input.fastForwardMode) { - int arg = 0; - ioctl(fbdev,FBIO_WAITFORVSYNC,&arg); + swapOnVSync = !settings.input.fastForwardMode; + eglSwapInterval(display, (int)swapOnVSync); } #endif eglSwapBuffers(display, surface); diff --git a/core/wsi/egl.h b/core/wsi/egl.h index a1aa122fc..945318fe4 100644 --- a/core/wsi/egl.h +++ b/core/wsi/egl.h @@ -55,6 +55,7 @@ private: #ifdef TARGET_PANDORA int fbdev = -1; #endif + bool swapOnVSync = false; }; extern EGLGraphicsContext theGLContext; diff --git a/core/wsi/sdl.cpp b/core/wsi/sdl.cpp index 843e6a46c..883dbd129 100644 --- a/core/wsi/sdl.cpp +++ b/core/wsi/sdl.cpp @@ -79,11 +79,12 @@ bool SDLGLGraphicsContext::Init() SDL_GL_MakeCurrent(window, glcontext); #ifndef TEST_AUTOMATION // Swap at vsync - SDL_GL_SetSwapInterval(1); + swapOnVSync = true; #else // Swap immediately - SDL_GL_SetSwapInterval(0); + swapOnVSync = false; #endif + SDL_GL_SetSwapInterval((int)swapOnVSync); #ifdef GLES load_gles_symbols(); @@ -103,6 +104,12 @@ void SDLGLGraphicsContext::Swap() { #ifdef TEST_AUTOMATION do_swap_automation(); +#else + if (swapOnVSync == settings.input.fastForwardMode) + { + swapOnVSync = !settings.input.fastForwardMode; + SDL_GL_SetSwapInterval((int)swapOnVSync); + } #endif SDL_GL_SwapWindow(window); diff --git a/core/wsi/sdl.h b/core/wsi/sdl.h index ec599ebae..d1f9c5b29 100644 --- a/core/wsi/sdl.h +++ b/core/wsi/sdl.h @@ -45,6 +45,7 @@ public: private: SDL_Window* window = nullptr; SDL_GLContext glcontext = nullptr; + bool swapOnVSync = false; }; extern SDLGLGraphicsContext theGLContext; diff --git a/core/wsi/xgl.cpp b/core/wsi/xgl.cpp index d29af2e0d..5e08d27af 100644 --- a/core/wsi/xgl.cpp +++ b/core/wsi/xgl.cpp @@ -82,6 +82,21 @@ bool XGLGraphicsContext::Init() unsigned int tempu; XGetGeometry(display, window, &win, &temp, &temp, (u32 *)&screen_width, (u32 *)&screen_height, &tempu, &tempu); +#ifndef TEST_AUTOMATION + swapOnVSync = true; +#else + swapOnVSync = false; +#endif + glXSwapIntervalMESA = (int (*)(unsigned))glXGetProcAddress((const GLubyte*)"glXSwapIntervalMESA"); + if (glXSwapIntervalMESA != nullptr) + glXSwapIntervalMESA((unsigned)swapOnVSync); + else + { + glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddress((const GLubyte*)"glXSwapIntervalEXT"); + if (glXSwapIntervalEXT != nullptr) + glXSwapIntervalEXT(display, window, (int)swapOnVSync); + } + PostInit(); return true; @@ -142,32 +157,22 @@ void XGLGraphicsContext::Swap() { #ifdef TEST_AUTOMATION do_swap_automation(); +#else + if (swapOnVSync == settings.input.fastForwardMode) + { + swapOnVSync = !settings.input.fastForwardMode; + if (glXSwapIntervalMESA != nullptr) + glXSwapIntervalMESA((unsigned)swapOnVSync); + else if (glXSwapIntervalEXT != nullptr) + glXSwapIntervalEXT(display, window, (int)swapOnVSync); + } #endif glXSwapBuffers(display, window); Window win; int temp; - unsigned int tempu, new_w, new_h; - XGetGeometry(display, window, &win, &temp, &temp, &new_w, &new_h, &tempu, &tempu); - - //if resized, clear up the draw buffers, to avoid out-of-draw-area junk data - if (new_w != screen_width || new_h != screen_height) { - screen_width = new_w; - screen_height = new_h; - } - -#if 0 - //handy to debug really stupid render-not-working issues ... - - glcache.ClearColor(0, 0.5, 1, 1); - glClear(GL_COLOR_BUFFER_BIT); - glXSwapBuffers(display, window); - - - glcache.ClearColor(1, 0.5, 0, 1); - glClear(GL_COLOR_BUFFER_BIT); - glXSwapBuffers(display, window); -#endif + unsigned int tempu; + XGetGeometry(display, window, &win, &temp, &temp, (u32 *)&screen_width, (u32 *)&screen_height, &tempu, &tempu); } void XGLGraphicsContext::Term() diff --git a/core/wsi/xgl.h b/core/wsi/xgl.h index 1280747fb..8f9fd6252 100644 --- a/core/wsi/xgl.h +++ b/core/wsi/xgl.h @@ -41,6 +41,9 @@ private: Display *display; GLXContext context; GLXFBConfig* framebufferConfigs = nullptr; + PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT = nullptr; + int (*glXSwapIntervalMESA)(unsigned int interval) = nullptr; + bool swapOnVSync = false; }; extern XGLGraphicsContext theGLContext;