Index: content/browser/renderer_host/compositing_iosurface_layer_mac.mm |
diff --git a/content/browser/renderer_host/compositing_iosurface_layer_mac.mm b/content/browser/renderer_host/compositing_iosurface_layer_mac.mm |
index af7f700f11ef00b2985816987ce564d27053084e..f96e07f925a01ee4a766dc5da238149bd36d3ec7 100644 |
--- a/content/browser/renderer_host/compositing_iosurface_layer_mac.mm |
+++ b/content/browser/renderer_host/compositing_iosurface_layer_mac.mm |
@@ -19,30 +19,41 @@ |
@implementation CompositingIOSurfaceLayer |
-- (id)initWithRenderWidgetHostViewMac:(content::RenderWidgetHostViewMac*)r { |
+- (content::CompositingIOSurfaceMac*)iosurface { |
+ return iosurface_.get(); |
+} |
+ |
+- (content::CompositingIOSurfaceContext*)context { |
+ return context_.get(); |
+} |
+ |
+- (id)initWithIOSurface:(scoped_refptr<content::CompositingIOSurfaceMac>) |
+ iosurface |
+ withClient:(content::CompositingIOSurfaceLayerClient*)client { |
if (self = [super init]) { |
- renderWidgetHostView_ = r; |
+ iosurface_ = iosurface; |
+ client_ = client; |
+ |
context_ = content::CompositingIOSurfaceContext::Get( |
content::CompositingIOSurfaceContext::kCALayerContextWindowNumber); |
DCHECK(context_); |
- needsDisplay_ = NO; |
+ needs_display_ = NO; |
+ did_not_draw_counter_ = 0; |
[self setBackgroundColor:CGColorGetConstantColor(kCGColorWhite)]; |
[self setAnchorPoint:CGPointMake(0, 0)]; |
// Setting contents gravity is necessary to prevent the layer from being |
// scaled during dyanmic resizes (especially with devtools open). |
[self setContentsGravity:kCAGravityTopLeft]; |
- if (renderWidgetHostView_->compositing_iosurface_ && |
- [self respondsToSelector:(@selector(setContentsScale:))]) { |
- [self setContentsScale: |
- renderWidgetHostView_->compositing_iosurface_->scale_factor()]; |
+ if ([self respondsToSelector:(@selector(setContentsScale:))]) { |
+ [self setContentsScale:iosurface_->scale_factor()]; |
} |
} |
return self; |
} |
-- (void)disableCompositing{ |
- renderWidgetHostView_ = nil; |
+- (void)resetClient { |
+ client_ = NULL; |
} |
- (void)gotNewFrame { |
@@ -55,32 +66,16 @@ |
// Calls to setNeedsDisplay can sometimes be ignored, especially if issued |
// rapidly (e.g, with vsync off). This is unacceptable because the failure |
// to ack a single frame will hang the renderer. Ensure that the renderer |
- // not be blocked. |
- if (needsDisplay_) |
- renderWidgetHostView_->SendPendingSwapAck(); |
+ // not be blocked by lying and claiming that we drew the frame. |
+ if (needs_display_ && client_) |
+ client_->AcceleratedLayerDidDrawFrame(true); |
} else { |
- needsDisplay_ = YES; |
+ needs_display_ = YES; |
if (![self isAsynchronous]) |
[self setAsynchronous:YES]; |
} |
} |
-- (void)timerSinceGotNewFrameFired { |
- if (![self isAsynchronous]) |
- return; |
- |
- [self setAsynchronous:NO]; |
- |
- // If there was a pending frame, ensure that it goes through. |
- if (needsDisplay_) { |
- [self setNeedsDisplay]; |
- [self displayIfNeeded]; |
- } |
- // If that fails then ensure that, at a minimum, the renderer is not blocked. |
- if (needsDisplay_) |
- renderWidgetHostView_->SendPendingSwapAck(); |
-} |
- |
// The remaining methods implement the CAOpenGLLayer interface. |
- (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask { |
@@ -96,7 +91,7 @@ |
} |
- (void)setNeedsDisplay { |
- needsDisplay_ = YES; |
+ needs_display_ = YES; |
[super setNeedsDisplay]; |
} |
@@ -104,9 +99,6 @@ |
pixelFormat:(CGLPixelFormatObj)pixelFormat |
forLayerTime:(CFTimeInterval)timeInterval |
displayTime:(const CVTimeStamp*)timeStamp { |
- if (!renderWidgetHostView_) |
- return NO; |
- |
// Add an instantaneous blip to the PendingSwapAck state to indicate |
// that CoreAnimation asked if a frame is ready. A blip up to to 3 (usually |
// from 2, indicating that a swap ack is pending) indicates that we requested |
@@ -114,12 +106,24 @@ |
// ack) indicates that we did not request a draw. This would be more natural |
// to do with a tracing pseudo-thread |
// http://crbug.com/366300 |
- TRACE_COUNTER_ID1("browser", "PendingSwapAck", renderWidgetHostView_, |
- needsDisplay_ ? 3 : 1); |
- TRACE_COUNTER_ID1("browser", "PendingSwapAck", renderWidgetHostView_, |
- renderWidgetHostView_->HasPendingSwapAck() ? 2 : 0); |
+ if (client_) { |
+ TRACE_COUNTER_ID1("browser", "PendingSwapAck", self, |
+ needs_display_ ? 3 : 1); |
+ TRACE_COUNTER_ID1("browser", "PendingSwapAck", self, |
+ client_->AcceleratedLayerHasNotAckedPendingFrame() ? 2 : 0); |
+ } |
- return needsDisplay_; |
+ // If we return NO 30 times in a row, switch to being synchronous to avoid |
+ // burning CPU cycles on this callback. |
+ if (needs_display_) { |
+ did_not_draw_counter_ = 0; |
+ } else { |
+ did_not_draw_counter_ += 1; |
+ if (did_not_draw_counter_ > 30) |
+ [self setAsynchronous:NO]; |
+ } |
+ |
+ return needs_display_; |
} |
- (void)drawInCGLContext:(CGLContextObj)glContext |
@@ -128,11 +132,7 @@ |
displayTime:(const CVTimeStamp*)timeStamp { |
TRACE_EVENT0("browser", "CompositingIOSurfaceLayer::drawInCGLContext"); |
- if (!context_ || |
- (context_ && context_->cgl_context() != glContext) || |
- !renderWidgetHostView_ || |
- !renderWidgetHostView_->compositing_iosurface_ || |
- !renderWidgetHostView_->compositing_iosurface_->HasIOSurface()) { |
+ if (!iosurface_->HasIOSurface() || context_->cgl_context() != glContext) { |
glClearColor(1, 1, 1, 1); |
glClear(GL_COLOR_BUFFER_BIT); |
return; |
@@ -150,18 +150,12 @@ |
window_rect = ToNearestRect( |
gfx::ScaleRect(window_rect, 1.f/window_scale_factor)); |
- if (!renderWidgetHostView_->compositing_iosurface_->DrawIOSurface( |
- context_, |
- window_rect, |
- window_scale_factor, |
- false)) { |
- renderWidgetHostView_->GotAcceleratedCompositingError(); |
- return; |
- } |
+ bool draw_succeeded = iosurface_->DrawIOSurface( |
+ context_, window_rect, window_scale_factor, false); |
- needsDisplay_ = NO; |
- renderWidgetHostView_->SendPendingLatencyInfoToHost(); |
- renderWidgetHostView_->SendPendingSwapAck(); |
+ needs_display_ = NO; |
+ if (client_) |
+ client_->AcceleratedLayerDidDrawFrame(draw_succeeded); |
[super drawInCGLContext:glContext |
pixelFormat:pixelFormat |