Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(633)

Unified Diff: content/browser/renderer_host/compositing_iosurface_mac.mm

Issue 10828104: fix mac frame-rate regression for non-threaded GPU compositing (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: remove DEPS change Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/renderer_host/compositing_iosurface_mac.mm
diff --git a/content/browser/renderer_host/compositing_iosurface_mac.mm b/content/browser/renderer_host/compositing_iosurface_mac.mm
index 8059e11686da59b4cdbccda39010a6a24446091f..361ffeeb0bd45f6c3e2150e570bd670b9cb3b596 100644
--- a/content/browser/renderer_host/compositing_iosurface_mac.mm
+++ b/content/browser/renderer_host/compositing_iosurface_mac.mm
@@ -9,6 +9,7 @@
#include "base/command_line.h"
#include "base/debug/trace_event.h"
+#include "base/threading/platform_thread.h"
#include "content/browser/renderer_host/render_widget_host_view_mac.h"
#include "content/public/browser/browser_thread.h"
#include "gpu/command_buffer/service/gpu_switches.h"
@@ -31,26 +32,26 @@
namespace content {
namespace {
-static const char* g_vertex_shader_blit_rgb = SHADER_STRING_GLSL(
+const char* g_vertex_shader_blit_rgb = SHADER_STRING_GLSL(
varying vec2 texture_coordinate;
void main() {
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
texture_coordinate = vec2(gl_MultiTexCoord0);
});
-static const char* g_fragment_shader_blit_rgb = SHADER_STRING_GLSL(
+const char* g_fragment_shader_blit_rgb = SHADER_STRING_GLSL(
varying vec2 texture_coordinate;
uniform sampler2DRect texture;
void main() {
gl_FragColor = vec4(texture2DRect(texture, texture_coordinate).rgb, 1.0);
});
-static const char* g_vertex_shader_white = SHADER_STRING_GLSL(
+const char* g_vertex_shader_white = SHADER_STRING_GLSL(
void main() {
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
});
-static const char* g_fragment_shader_white = SHADER_STRING_GLSL(
+const char* g_fragment_shader_white = SHADER_STRING_GLSL(
void main() {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
});
@@ -105,6 +106,18 @@ GLuint CreateProgramGLSL(const char* vertex_shader_str,
} // namespace
+CVReturn DisplayLinkCallback(CVDisplayLinkRef display_link,
+ const CVTimeStamp* now,
+ const CVTimeStamp* output_time,
+ CVOptionFlags flags_in,
+ CVOptionFlags* flags_out,
+ void* context) {
+ CompositingIOSurfaceMac* surface =
+ static_cast<CompositingIOSurfaceMac*>(context);
+ surface->DisplayLinkTick(display_link, output_time);
+ return kCVReturnSuccess;
+}
+
CompositingIOSurfaceMac* CompositingIOSurfaceMac::Create() {
TRACE_EVENT0("browser", "CompositingIOSurfaceMac::Create");
IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize();
@@ -169,12 +182,33 @@ CompositingIOSurfaceMac* CompositingIOSurfaceMac::Create() {
return NULL;
}
+ CVDisplayLinkRef display_link;
+ CVReturn ret = CVDisplayLinkCreateWithActiveCGDisplays(&display_link);
+ if (ret != kCVReturnSuccess) {
+ LOG(ERROR) << "CVDisplayLinkCreateWithActiveCGDisplays failed: " << ret;
+ return NULL;
+ }
+
+ // Set the display link for the current renderer
+ CGLPixelFormatObj cglPixelFormat =
+ (CGLPixelFormatObj)[glPixelFormat CGLPixelFormatObj];
+ ret = CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(display_link,
+ cglContext,
+ cglPixelFormat);
+ if (ret != kCVReturnSuccess) {
+ CVDisplayLinkRelease(display_link);
+ LOG(ERROR) << "CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext failed: "
+ << ret;
+ return NULL;
+ }
+
return new CompositingIOSurfaceMac(io_surface_support, glContext.release(),
cglContext,
shader_program_blit_rgb,
blit_rgb_sampler_location,
shader_program_white,
- is_vsync_disabled);
+ is_vsync_disabled,
+ display_link);
}
CompositingIOSurfaceMac::CompositingIOSurfaceMac(
@@ -184,7 +218,8 @@ CompositingIOSurfaceMac::CompositingIOSurfaceMac(
GLuint shader_program_blit_rgb,
GLint blit_rgb_sampler_location,
GLuint shader_program_white,
- bool is_vsync_disabled)
+ bool is_vsync_disabled,
+ CVDisplayLinkRef display_link)
: io_surface_support_(io_surface_support),
glContext_(glContext),
cglContext_(cglContext),
@@ -193,10 +228,45 @@ CompositingIOSurfaceMac::CompositingIOSurfaceMac(
shader_program_blit_rgb_(shader_program_blit_rgb),
blit_rgb_sampler_location_(blit_rgb_sampler_location),
shader_program_white_(shader_program_white),
- is_vsync_disabled_(is_vsync_disabled) {
+ is_vsync_disabled_(is_vsync_disabled),
+ display_link_(display_link),
+ display_link_stop_timer_(FROM_HERE, base::TimeDelta::FromSeconds(1),
+ this, &CompositingIOSurfaceMac::StopDisplayLink),
+ vsync_count_(0),
+ swap_count_(0),
+ vsync_interval_numerator_(0),
+ vsync_interval_denominator_(0) {
+ CVReturn ret = CVDisplayLinkSetOutputCallback(display_link_,
+ &DisplayLinkCallback, this);
+ DCHECK(ret == kCVReturnSuccess)
+ << "CVDisplayLinkSetOutputCallback failed: " << ret;
+
+ StartOrContinueDisplayLink();
+
+ CVTimeStamp cv_time;
+ ret = CVDisplayLinkGetCurrentTime(display_link_, &cv_time);
+ DCHECK(ret == kCVReturnSuccess)
+ << "CVDisplayLinkGetCurrentTime failed: " << ret;
+
+ {
+ base::AutoLock lock(lock_);
+ CalculateVsyncParametersLockHeld(&cv_time);
+ }
+
+ // Stop display link for now, it will be started when needed during Draw.
+ StopDisplayLink();
+}
+
+void CompositingIOSurfaceMac::GetVSyncParameters(base::TimeTicks* timebase,
+ uint32* interval_numerator,
+ uint32* interval_denominator) {
+ *timebase = vsync_timebase_;
+ *interval_numerator = vsync_interval_numerator_;
+ *interval_denominator = vsync_interval_denominator_;
}
CompositingIOSurfaceMac::~CompositingIOSurfaceMac() {
+ CVDisplayLinkRelease(display_link_);
UnrefIOSurface();
}
@@ -300,7 +370,15 @@ void CompositingIOSurfaceMac::DrawIOSurface(NSView* view, float scale_factor) {
CGLFlushDrawable(cglContext_);
+ // For latency_tests.cc:
+ UNSHIPPED_TRACE_EVENT_INSTANT0("test_gpu", "CompositorSwapBuffersComplete");
+
CGLSetCurrentContext(0);
+
+ StartOrContinueDisplayLink();
+
+ if (!is_vsync_disabled_)
+ RateLimitDraws();
}
bool CompositingIOSurfaceMac::CopyTo(const gfx::Size& dst_size, void* out) {
@@ -467,4 +545,64 @@ void CompositingIOSurfaceMac::ClearDrawable() {
UnrefIOSurface();
}
+void CompositingIOSurfaceMac::DisplayLinkTick(CVDisplayLinkRef display_link,
+ const CVTimeStamp* output_time) {
+ base::AutoLock lock(lock_);
+ // Increment vsync_count but don't let it get ahead of swap_count.
+ vsync_count_ = std::min(vsync_count_ + 1, swap_count_);
+
+ CalculateVsyncParametersLockHeld(output_time);
+}
+
+void CompositingIOSurfaceMac::CalculateVsyncParametersLockHeld(
+ const CVTimeStamp* time) {
+ vsync_interval_numerator_ = static_cast<uint32>(time->videoRefreshPeriod);
+ vsync_interval_denominator_ = time->videoTimeScale;
+ // Verify that videoRefreshPeriod is 32 bits.
+ DCHECK((time->videoRefreshPeriod & ~0xffffFFFFull) == 0ull);
+
+ vsync_timebase_ =
+ base::TimeTicks::FromInternalValue(time->hostTime / 1000);
+}
+
+void CompositingIOSurfaceMac::RateLimitDraws() {
+ int64 vsync_count;
+ int64 swap_count;
+
+ {
+ base::AutoLock lock(lock_);
+ vsync_count = vsync_count_;
+ swap_count = ++swap_count_;
vangelis 2012/08/01 00:53:12 Should these two values be reset somewhere on a su
jbates 2012/08/01 01:00:47 They get reset when the 1 second idle timer fires.
vangelis 2012/08/01 01:33:01 Oh, I see. That makes sense.
+ }
+
+ // It's OK for swap_count to get 2 ahead of vsync_count, but any more
+ // indicates that it has become unthrottled. This happens when, for example,
+ // the window is obscured by another opaque window.
+ if (swap_count > vsync_count + 2) {
+ TRACE_EVENT0("gpu", "CompositingIOSurfaceMac::RateLimitDraws");
+ // Sleep for one vsync interval. This will prevent spinning while the window
+ // is not visible, but will also allow quick recovery when the window
+ // becomes visible again.
+ int64 sleep_us = 16666; // default to 60hz if display link API fails.
+ if (vsync_interval_denominator_ > 0) {
+ sleep_us = (static_cast<int64>(vsync_interval_numerator_) * 1000000) /
+ vsync_interval_denominator_;
+ }
+ base::PlatformThread::Sleep(base::TimeDelta::FromMicroseconds(sleep_us));
+ }
+}
+
+void CompositingIOSurfaceMac::StartOrContinueDisplayLink() {
+ if (!CVDisplayLinkIsRunning(display_link_)) {
+ vsync_count_ = swap_count_ = 0;
+ CVDisplayLinkStart(display_link_);
+ }
+ display_link_stop_timer_.Reset();
+}
+
+void CompositingIOSurfaceMac::StopDisplayLink() {
+ if (CVDisplayLinkIsRunning(display_link_))
+ CVDisplayLinkStop(display_link_);
+}
+
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698