summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbajones <bajones@chromium.org>2015-01-02 15:37:41 -0800
committerCommit bot <commit-bot@chromium.org>2015-01-02 23:38:25 +0000
commit9b71e13d22829c2df1620211049a6032628ebea8 (patch)
tree50e82a225d0d8adc6889ad67e4b7fbbe289f8d90
parentb1fc43cac3ab16b3218b72370225dd3a6456a671 (diff)
downloadchromium_src-9b71e13d22829c2df1620211049a6032628ebea8.zip
chromium_src-9b71e13d22829c2df1620211049a6032628ebea8.tar.gz
chromium_src-9b71e13d22829c2df1620211049a6032628ebea8.tar.bz2
Allow Windows to use system Vsync if only one window is swapping
This makes the common case (single browser window) smoother. Having multiple swapping windows visible will force the previous behavior. This patch differs from a previous variant (https://codereview.chromium.org/708483003) in that there's now a "timeout" before we attempt turning on vsync again. Specifically, we need to go for 60 frames without a frame where two surfaces swap in order to turn Vsync on. This accounts for cases where low-frequency updates in one window (blinking cursor) don't trigger frequent vsync state changes. Also prevents pathologically bad cases where two frequently updating windows would cause one another to skip alternating frames. BUG=422000 Review URL: https://codereview.chromium.org/749483002 Cr-Commit-Position: refs/heads/master@{#309861}
-rw-r--r--content/common/gpu/image_transport_surface.cc12
-rw-r--r--ui/gl/gl_context_egl.cc8
-rw-r--r--ui/gl/gl_context_egl.h1
-rw-r--r--ui/gl/gl_surface.cc3
-rw-r--r--ui/gl/gl_surface.h3
-rw-r--r--ui/gl/gl_surface_egl.cc52
-rw-r--r--ui/gl/gl_surface_egl.h13
7 files changed, 78 insertions, 14 deletions
diff --git a/content/common/gpu/image_transport_surface.cc b/content/common/gpu/image_transport_surface.cc
index bb11dd8..75be58d 100644
--- a/content/common/gpu/image_transport_surface.cc
+++ b/content/common/gpu/image_transport_surface.cc
@@ -18,10 +18,6 @@
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_switches.h"
-#if defined(OS_WIN)
-#include "ui/base/win/shell.h"
-#endif
-
namespace content {
ImageTransportSurface::ImageTransportSurface() {}
@@ -137,14 +133,6 @@ bool ImageTransportHelper::MakeCurrent() {
}
void ImageTransportHelper::SetSwapInterval(gfx::GLContext* context) {
-#if defined(OS_WIN)
- // If Aero Glass is enabled, then the renderer will handle ratelimiting and
- // there's no tearing, so waiting for vsync is unnecessary.
- if (ui::win::IsAeroGlassEnabled()) {
- context->ForceSwapIntervalZero(true);
- return;
- }
-#endif
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableGpuVsync))
context->ForceSwapIntervalZero(true);
diff --git a/ui/gl/gl_context_egl.cc b/ui/gl/gl_context_egl.cc
index 5dd1aaf..076de98 100644
--- a/ui/gl/gl_context_egl.cc
+++ b/ui/gl/gl_context_egl.cc
@@ -29,7 +29,8 @@ GLContextEGL::GLContextEGL(GLShareGroup* share_group)
context_(NULL),
display_(NULL),
config_(NULL),
- unbind_fbo_on_makecurrent_(false) {
+ unbind_fbo_on_makecurrent_(false),
+ swap_interval_(1) {
}
bool GLContextEGL::Initialize(
@@ -125,6 +126,8 @@ bool GLContextEGL::MakeCurrent(GLSurface* surface) {
return false;
}
+ surface->OnSetSwapInterval(swap_interval_);
+
release_current.Cancel();
return true;
}
@@ -183,6 +186,9 @@ void GLContextEGL::OnSetSwapInterval(int interval) {
if (!eglSwapInterval(display_, interval)) {
LOG(ERROR) << "eglSwapInterval failed with error "
<< GetLastEGLErrorString();
+ } else {
+ swap_interval_ = interval;
+ GLSurface::GetCurrent()->OnSetSwapInterval(interval);
}
}
diff --git a/ui/gl/gl_context_egl.h b/ui/gl/gl_context_egl.h
index 99a4481..39b26d0 100644
--- a/ui/gl/gl_context_egl.h
+++ b/ui/gl/gl_context_egl.h
@@ -45,6 +45,7 @@ class GLContextEGL : public GLContextReal {
EGLDisplay display_;
EGLConfig config_;
bool unbind_fbo_on_makecurrent_;
+ int swap_interval_;
DISALLOW_COPY_AND_ASSIGN(GLContextEGL);
};
diff --git a/ui/gl/gl_surface.cc b/ui/gl/gl_surface.cc
index e1369e5..ed91944 100644
--- a/ui/gl/gl_surface.cc
+++ b/ui/gl/gl_surface.cc
@@ -290,6 +290,9 @@ bool GLSurface::ExtensionsContain(const char* c_extensions, const char* name) {
return extensions.find(delimited_name) != std::string::npos;
}
+void GLSurface::OnSetSwapInterval(int interval) {
+}
+
GLSurfaceAdapter::GLSurfaceAdapter(GLSurface* surface) : surface_(surface) {}
bool GLSurfaceAdapter::Initialize() {
diff --git a/ui/gl/gl_surface.h b/ui/gl/gl_surface.h
index cc487be..3220be6 100644
--- a/ui/gl/gl_surface.h
+++ b/ui/gl/gl_surface.h
@@ -162,6 +162,9 @@ class GL_EXPORT GLSurface : public base::RefCounted<GLSurface> {
static GLSurface* GetCurrent();
+ // Called when the swap interval for the associated context changes.
+ virtual void OnSetSwapInterval(int interval);
+
protected:
virtual ~GLSurface();
static bool InitializeOneOffImplementation(GLImplementation impl,
diff --git a/ui/gl/gl_surface_egl.cc b/ui/gl/gl_surface_egl.cc
index 193eebf..1b670e1 100644
--- a/ui/gl/gl_surface_egl.cc
+++ b/ui/gl/gl_surface_egl.cc
@@ -57,6 +57,14 @@ using ui::GetLastEGLErrorString;
namespace gfx {
+#if defined(OS_WIN)
+unsigned int NativeViewGLSurfaceEGL::current_swap_generation_ = 0;
+unsigned int NativeViewGLSurfaceEGL::swaps_this_generation_ = 0;
+unsigned int NativeViewGLSurfaceEGL::last_multiswap_generation_ = 0;
+
+const unsigned int MULTISWAP_FRAME_VSYNC_THRESHOLD = 60;
+#endif
+
namespace {
EGLConfig g_config;
@@ -341,13 +349,16 @@ NativeViewGLSurfaceEGL::NativeViewGLSurfaceEGL(EGLNativeWindowType window)
surface_(NULL),
supports_post_sub_buffer_(false),
config_(NULL),
- size_(1, 1) {
+ size_(1, 1),
+ swap_interval_(1) {
#if defined(OS_ANDROID)
if (window)
ANativeWindow_acquire(window);
#endif
#if defined(OS_WIN)
+ vsync_override_ = false;
+ swap_generation_ = 0;
RECT windowRect;
if (GetClientRect(window_, &windowRect))
size_ = gfx::Rect(windowRect).size();
@@ -505,6 +516,41 @@ bool NativeViewGLSurfaceEGL::SwapBuffers() {
"width", GetSize().width(),
"height", GetSize().height());
+#if defined(OS_WIN)
+ if (swap_interval_ != 0) {
+ // This code is a simple way of enforcing that we only vsync if one surface
+ // is swapping per frame. This provides single window cases a stable refresh
+ // while allowing multi-window cases to not slow down due to multiple syncs
+ // on a single thread. A better way to fix this problem would be to have
+ // each surface present on its own thread.
+
+ if (current_swap_generation_ == swap_generation_) {
+ if (swaps_this_generation_ > 1)
+ last_multiswap_generation_ = current_swap_generation_;
+ swaps_this_generation_ = 0;
+ current_swap_generation_++;
+ }
+
+ swap_generation_ = current_swap_generation_;
+
+ if (swaps_this_generation_ != 0 ||
+ (current_swap_generation_ - last_multiswap_generation_ <
+ MULTISWAP_FRAME_VSYNC_THRESHOLD)) {
+ // Override vsync settings and switch it off
+ if (!vsync_override_) {
+ eglSwapInterval(GetDisplay(), 0);
+ vsync_override_ = true;
+ }
+ } else if (vsync_override_) {
+ // Only one window swapping, so let the normal vsync setting take over
+ eglSwapInterval(GetDisplay(), swap_interval_);
+ vsync_override_ = false;
+ }
+
+ swaps_this_generation_++;
+ }
+#endif
+
if (!eglSwapBuffers(GetDisplay(), surface_)) {
DVLOG(1) << "eglSwapBuffers failed with error "
<< GetLastEGLErrorString();
@@ -585,6 +631,10 @@ VSyncProvider* NativeViewGLSurfaceEGL::GetVSyncProvider() {
return vsync_provider_.get();
}
+void NativeViewGLSurfaceEGL::OnSetSwapInterval(int interval) {
+ swap_interval_ = interval;
+}
+
NativeViewGLSurfaceEGL::~NativeViewGLSurfaceEGL() {
Destroy();
#if defined(OS_ANDROID)
diff --git a/ui/gl/gl_surface_egl.h b/ui/gl/gl_surface_egl.h
index 720c7dd..767ed7b 100644
--- a/ui/gl/gl_surface_egl.h
+++ b/ui/gl/gl_surface_egl.h
@@ -83,6 +83,8 @@ class GL_EXPORT NativeViewGLSurfaceEGL : public GLSurfaceEGL {
EGLNativeWindowType window_;
+ void OnSetSwapInterval(int interval) override;
+
private:
EGLSurface surface_;
bool supports_post_sub_buffer_;
@@ -91,6 +93,17 @@ class GL_EXPORT NativeViewGLSurfaceEGL : public GLSurfaceEGL {
scoped_ptr<VSyncProvider> vsync_provider_;
+ int swap_interval_;
+
+#if defined(OS_WIN)
+ bool vsync_override_;
+
+ unsigned int swap_generation_;
+ static unsigned int current_swap_generation_;
+ static unsigned int swaps_this_generation_;
+ static unsigned int last_multiswap_generation_;
+#endif
+
DISALLOW_COPY_AND_ASSIGN(NativeViewGLSurfaceEGL);
};