Commit 33ad4cc3 authored by ccameron@chromium.org's avatar ccameron@chromium.org

Mac: Fix janky YouTube animations

Based on experimentation, it appears that calling setNeedsDisplay or
displayIfNeeded on a CAOpenGLLayer which has the isAsynchronous
property set, will result in the animation getting screwed up. In
particular, calls to canDrawInCGLContext stop occurring.

This was working in M35 and M36 because, entirely accidentally, we
were calling setAsynchronous:NO before most instances of
setNeedsDisplay and displayIfNeeded. In r272469, these calls were
removed, and resulting in the janky animation.

Add calls to setAsynchronous:NO before all instances of calling
displayIfNeeded, and almost all instances of calling setNeedsDisplay.

BUG=395827
TEST=manual, automated tests in progress

Review URL: https://codereview.chromium.org/408153002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@284916 0039d316-1c4b-4281-b951-d872f2087c98
parent 0b6a800e
...@@ -147,10 +147,8 @@ void BrowserCompositorViewMacInternal::GotAcceleratedIOSurfaceFrame( ...@@ -147,10 +147,8 @@ void BrowserCompositorViewMacInternal::GotAcceleratedIOSurfaceFrame(
bool bounds_changed = !CGRectEqualToRect( bool bounds_changed = !CGRectEqualToRect(
new_layer_bounds, [accelerated_layer_ bounds]); new_layer_bounds, [accelerated_layer_ bounds]);
[accelerated_layer_ setBounds:new_layer_bounds]; [accelerated_layer_ setBounds:new_layer_bounds];
if (bounds_changed) { if (bounds_changed)
[accelerated_layer_ setNeedsDisplay]; [accelerated_layer_ setNeedsDisplayAndDisplayAndAck];
[accelerated_layer_ displayIfNeeded];
}
// If there was a software layer or an old accelerated layer, remove it. // If there was a software layer or an old accelerated layer, remove it.
// Disable the fade-out animation as the layer is removed. // Disable the fade-out animation as the layer is removed.
......
...@@ -51,10 +51,14 @@ class CompositingIOSurfaceLayerHelper { ...@@ -51,10 +51,14 @@ class CompositingIOSurfaceLayerHelper {
// frame. // frame.
void DidDraw(bool success); void DidDraw(bool success);
// Immediately re-draw the layer, even if the content has not changed, and
// ensure that the frame be acked.
void SetNeedsDisplayAndDisplayAndAck();
// Immediately draw the layer, only if one is pending, and ensure that the
// frame be acked.
void DisplayIfNeededAndAck();
private: private:
// Immediately draw a frame (disregarding vsync) and ensure that the frame is
// acknowledged.
void ImmediatelyForceDisplayAndAck();
// Called whenever the frame provided in GotNewFrame should be acknowledged // Called whenever the frame provided in GotNewFrame should be acknowledged
// (this may be because it was drawn, or it may be to unblock the // (this may be because it was drawn, or it may be to unblock the
...@@ -114,6 +118,13 @@ class CompositingIOSurfaceLayerHelper { ...@@ -114,6 +118,13 @@ class CompositingIOSurfaceLayerHelper {
// Called when a new frame is received. // Called when a new frame is received.
- (void)gotNewFrame; - (void)gotNewFrame;
// Force a draw immediately (even if this means re-displaying a previously
// displayed frame).
- (void)setNeedsDisplayAndDisplayAndAck;
// Force a draw immediately, but only if one was requested.
- (void)displayIfNeededAndAck;
@end @end
#endif // CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_LAYER_MAC_H_ #endif // CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_LAYER_MAC_H_
...@@ -54,7 +54,7 @@ void CompositingIOSurfaceLayerHelper::GotNewFrame() { ...@@ -54,7 +54,7 @@ void CompositingIOSurfaceLayerHelper::GotNewFrame() {
// If reqested, draw immediately and don't bother trying to use the // If reqested, draw immediately and don't bother trying to use the
// isAsynchronous property to ensure smooth animation. // isAsynchronous property to ensure smooth animation.
if (client_->AcceleratedLayerShouldAckImmediately()) { if (client_->AcceleratedLayerShouldAckImmediately()) {
ImmediatelyForceDisplayAndAck(); SetNeedsDisplayAndDisplayAndAck();
} else { } else {
if (![layer_ isAsynchronous]) if (![layer_ isAsynchronous])
[layer_ setAsynchronous:YES]; [layer_ setAsynchronous:YES];
...@@ -104,8 +104,29 @@ void CompositingIOSurfaceLayerHelper::AckPendingFrame(bool success) { ...@@ -104,8 +104,29 @@ void CompositingIOSurfaceLayerHelper::AckPendingFrame(bool success) {
TRACE_COUNTER_ID1("browser", "PendingSwapAck", this, 0); TRACE_COUNTER_ID1("browser", "PendingSwapAck", this, 0);
} }
void CompositingIOSurfaceLayerHelper::ImmediatelyForceDisplayAndAck() { void CompositingIOSurfaceLayerHelper::SetNeedsDisplayAndDisplayAndAck() {
// Drawing using setNeedsDisplay and displayIfNeeded will result in
// subsequent canDrawInCGLContext callbacks getting dropped, and jerky
// animation. Disable asynchronous drawing before issuing these calls as a
// workaround.
// http://crbug.com/395827
if ([layer_ isAsynchronous])
[layer_ setAsynchronous:NO];
[layer_ setNeedsDisplay]; [layer_ setNeedsDisplay];
DisplayIfNeededAndAck();
}
void CompositingIOSurfaceLayerHelper::DisplayIfNeededAndAck() {
if (!needs_display_)
return;
// As in SetNeedsDisplayAndDisplayAndAck, disable asynchronous drawing before
// issuing displayIfNeeded.
// http://crbug.com/395827
if ([layer_ isAsynchronous])
[layer_ setAsynchronous:NO];
[layer_ displayIfNeeded]; [layer_ displayIfNeeded];
// Calls to setNeedsDisplay can sometimes be ignored, especially if issued // Calls to setNeedsDisplay can sometimes be ignored, especially if issued
...@@ -116,7 +137,7 @@ void CompositingIOSurfaceLayerHelper::ImmediatelyForceDisplayAndAck() { ...@@ -116,7 +137,7 @@ void CompositingIOSurfaceLayerHelper::ImmediatelyForceDisplayAndAck() {
} }
void CompositingIOSurfaceLayerHelper::TimerFired() { void CompositingIOSurfaceLayerHelper::TimerFired() {
ImmediatelyForceDisplayAndAck(); SetNeedsDisplayAndDisplayAndAck();
} }
} // namespace content } // namespace content
...@@ -171,6 +192,14 @@ void CompositingIOSurfaceLayerHelper::TimerFired() { ...@@ -171,6 +192,14 @@ void CompositingIOSurfaceLayerHelper::TimerFired() {
helper_->GotNewFrame(); helper_->GotNewFrame();
} }
- (void)setNeedsDisplayAndDisplayAndAck {
helper_->SetNeedsDisplayAndDisplayAndAck();
}
- (void)displayIfNeededAndAck {
helper_->DisplayIfNeededAndAck();
}
// The remaining methods implement the CAOpenGLLayer interface. // The remaining methods implement the CAOpenGLLayer interface.
- (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask { - (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask {
......
...@@ -1779,8 +1779,8 @@ void RenderWidgetHostViewMac::AcceleratedSurfacePostSubBuffer( ...@@ -1779,8 +1779,8 @@ void RenderWidgetHostViewMac::AcceleratedSurfacePostSubBuffer(
} }
void RenderWidgetHostViewMac::AcceleratedSurfaceSuspend() { void RenderWidgetHostViewMac::AcceleratedSurfaceSuspend() {
if (compositing_iosurface_) if (render_widget_host_->is_hidden())
compositing_iosurface_->UnrefIOSurface(); DestroyCompositedIOSurfaceAndLayer();
} }
void RenderWidgetHostViewMac::AcceleratedSurfaceRelease() { void RenderWidgetHostViewMac::AcceleratedSurfaceRelease() {
...@@ -2206,7 +2206,7 @@ void RenderWidgetHostViewMac::PauseForPendingResizeOrRepaintsAndDraw() { ...@@ -2206,7 +2206,7 @@ void RenderWidgetHostViewMac::PauseForPendingResizeOrRepaintsAndDraw() {
// to keep the window and the window's contents in sync. // to keep the window and the window's contents in sync.
[cocoa_view_ displayIfNeeded]; [cocoa_view_ displayIfNeeded];
[software_layer_ displayIfNeeded]; [software_layer_ displayIfNeeded];
[compositing_iosurface_layer_ displayIfNeeded]; [compositing_iosurface_layer_ displayIfNeededAndAck];
} }
void RenderWidgetHostViewMac::LayoutLayers() { void RenderWidgetHostViewMac::LayoutLayers() {
...@@ -2250,8 +2250,7 @@ void RenderWidgetHostViewMac::LayoutLayers() { ...@@ -2250,8 +2250,7 @@ void RenderWidgetHostViewMac::LayoutLayers() {
// displayed. Calling displayIfNeeded will ensure that the right size // displayed. Calling displayIfNeeded will ensure that the right size
// frame is drawn to the screen. // frame is drawn to the screen.
// http://crbug.com/350817 // http://crbug.com/350817
[compositing_iosurface_layer_ setNeedsDisplay]; [compositing_iosurface_layer_ setNeedsDisplayAndDisplayAndAck];
[compositing_iosurface_layer_ displayIfNeeded];
} }
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment