Index: ui/gl/gl_surface_egl.cc |
diff --git a/ui/gl/gl_surface_egl.cc b/ui/gl/gl_surface_egl.cc |
index 3b81daf83285a476768cb724f7facde9bbca8950..d8783f40efc83a7eaaf392170a7d8d6c9b2550f7 100644 |
--- a/ui/gl/gl_surface_egl.cc |
+++ b/ui/gl/gl_surface_egl.cc |
@@ -8,6 +8,7 @@ |
#include <android/native_window_jni.h> |
#endif |
+#include "base/debug/trace_event.h" |
#include "base/logging.h" |
#include "base/memory/scoped_ptr.h" |
#include "base/message_loop.h" |
@@ -221,7 +222,8 @@ NativeViewGLSurfaceEGL::NativeViewGLSurfaceEGL(bool software, |
: window_(window), |
surface_(NULL), |
supports_post_sub_buffer_(false), |
- config_(NULL) { |
+ config_(NULL), |
+ max_frame_latency_(0) { |
software_ = software; |
#if defined(OS_ANDROID) |
if (window) |
@@ -368,12 +370,33 @@ bool NativeViewGLSurfaceEGL::IsOffscreen() { |
} |
bool NativeViewGLSurfaceEGL::SwapBuffers() { |
+ // Create a fence for this frame. |
+ if (max_frame_latency_ > 0) { |
+ DCHECK_LE(frame_fences_.size(), max_frame_latency_ - 1); |
+ EGLSyncKHR fence = eglCreateSyncKHR(GetDisplay(), EGL_SYNC_FENCE_KHR, NULL); |
Sami
2013/04/24 10:44:18
I remember one driver where sync object creation w
epennerAtGoogle
2013/04/24 19:33:38
Will do.
|
+ frame_fences_.push_back(fence); |
+ } |
+ |
if (!eglSwapBuffers(GetDisplay(), surface_)) { |
DVLOG(1) << "eglSwapBuffers failed with error " |
<< GetLastEGLErrorString(); |
return false; |
} |
+ // SwapBuffers above will block above according to the driver's |
+ // maximum latency. We now block again according to our own. |
+ DCHECK_LE(frame_fences_.size(), max_frame_latency_); |
+ if (frame_fences_.size() == max_frame_latency_) { |
+ TRACE_EVENT0("cc", "NativeViewGLSurfaceEGL eglClientWaitSyncKHR"); |
+ // We shouldn't need the flush flag, as SwapBuffers |
+ // always triggers a flush. |
+ EGLint flags = 0; //EGL_SYNC_FLUSH_COMMANDS_BIT_KHR; |
+ EGLTimeKHR time = EGL_FOREVER_KHR; |
+ EGLSyncKHR fence = frame_fences_.front(); |
+ eglClientWaitSyncKHR(GetDisplay(), fence, flags, time); |
Sami
2013/04/24 10:44:18
Call eglDestroySyncKHR after waiting here to avoid
epennerAtGoogle
2013/04/24 19:33:38
Oops! Thanks!
|
+ frame_fences_.pop_front(); |
+ } |
+ |
return true; |
} |
@@ -439,7 +462,18 @@ VSyncProvider* NativeViewGLSurfaceEGL::GetVSyncProvider() { |
return vsync_provider_.get(); |
} |
+void NativeViewGLSurfaceEGL::SetMaximumFrameLatency(unsigned int frames) { |
+ while (frame_fences_.size() > frames) { |
+ eglDestroySyncKHR(GetDisplay(), frame_fences_.front()); |
+ frame_fences_.pop_front(); |
+ } |
+ max_frame_latency_ = frames; |
+} |
+ |
NativeViewGLSurfaceEGL::~NativeViewGLSurfaceEGL() { |
+ SetMaximumFrameLatency(0); |
+ DCHECK(!frame_fences_.size()); |
+ |
Destroy(); |
#if defined(OS_ANDROID) |
if (window_) |