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 63f9ca36748f7cbd7712eb8667026160e59ace79..dfcc5718da9ebc538a2381900ea03610af20acf9 100644 |
--- a/content/browser/renderer_host/compositing_iosurface_layer_mac.mm |
+++ b/content/browser/renderer_host/compositing_iosurface_layer_mac.mm |
@@ -16,6 +16,14 @@ |
#include "ui/gfx/size_conversions.h" |
#include "ui/gl/gpu_switching_manager.h" |
+@interface CompositingIOSurfaceLayer() |
+ |
+// Private method to wait for a frame of the right size if we're in an active |
+// resize. This may potentially dispatch select messages from the run loop. |
+- (void)waitForResizedFrameInContext:(CGLContextObj)glContext; |
+ |
+@end |
+ |
@implementation CompositingIOSurfaceLayer |
@synthesize context = context_; |
@@ -83,6 +91,41 @@ |
[self setNeedsDisplay]; |
} |
+- (void)waitForResizedFrameInContext:(CGLContextObj)glContext { |
+ // Cache a copy of renderWidgetHostView_ because it may be reset if |
+ // a software frame is received in GetBackingStore. |
+ content::RenderWidgetHostViewMac* cached_view = renderWidgetHostView_; |
+ if (!cached_view->render_widget_host_ || |
+ cached_view->render_widget_host_->is_hidden()) { |
+ return; |
+ } |
+ |
+ // Note that GetBackingStore can potentially spawn a nested run loop, which |
+ // may change the current GL context, or, because the GL contexts are |
+ // shared, may change the currently-bound FBO. Ensure that, when the run |
+ // loop returns, the original GL context remain current, and the original |
+ // FBO remain bound. |
+ // TODO(ccameron): This is far too fragile a mechanism to rely on. Find |
+ // a way to avoid doing this. |
+ GLuint previous_framebuffer = 0; |
+ glGetIntegerv(GL_FRAMEBUFFER_BINDING, |
+ reinterpret_cast<GLint*>(&previous_framebuffer)); |
+ { |
+ // If a resize is in progress then GetBackingStore request a frame of the |
+ // current window size and block until a frame of the right size comes in. |
+ // This makes the window content not lag behind the resize (at the cost of |
+ // blocking on the browser's main thread). |
+ gfx::ScopedCGLSetCurrentContext scoped_set_current_context(NULL); |
+ cached_view->about_to_validate_and_paint_ = true; |
+ (void)cached_view->render_widget_host_->GetBackingStore(true); |
+ cached_view->about_to_validate_and_paint_ = false; |
+ } |
+ CHECK_EQ(CGLGetCurrentContext(), glContext) |
+ << "original GL context failed to re-bind after nested run loop, " |
+ << "browser crash is imminent."; |
+ glBindFramebuffer(GL_FRAMEBUFFER, previous_framebuffer); |
+} |
+ |
// The remaining methods implement the CAOpenGLLayer interface. |
- (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask { |
@@ -124,36 +167,12 @@ |
return; |
} |
- // Cache a copy of renderWidgetHostView_ because it may be reset if |
- // a software frame is received in GetBackingStore. |
- content::RenderWidgetHostViewMac* cached_view = renderWidgetHostView_; |
+ // Acknowledge the frame before we potentially wait for a frame of the right |
+ // size. |
+ renderWidgetHostView_->SendPendingSwapAck(); |
- // If a resize is in progress then GetBackingStore request a frame of the |
- // current window size and block until a frame of the right size comes in. |
- // This makes the window content not lag behind the resize (at the cost of |
- // blocking on the browser's main thread). |
- if (cached_view->render_widget_host_) { |
- // Note that GetBackingStore can potentially spawn a nested run loop, which |
- // may change the current GL context, or, because the GL contexts are |
- // shared, may change the currently-bound FBO. Ensure that, when the run |
- // loop returns, the original GL context remain current, and the original |
- // FBO remain bound. |
- // TODO(ccameron): This is far too fragile a mechanism to rely on. Find |
- // a way to avoid doing this. |
- GLuint previous_framebuffer = 0; |
- glGetIntegerv(GL_FRAMEBUFFER_BINDING, |
- reinterpret_cast<GLint*>(&previous_framebuffer)); |
- { |
- gfx::ScopedCGLSetCurrentContext scoped_set_current_context(NULL); |
- cached_view->about_to_validate_and_paint_ = true; |
- (void)cached_view->render_widget_host_->GetBackingStore(true); |
- cached_view->about_to_validate_and_paint_ = false; |
- } |
- CHECK_EQ(CGLGetCurrentContext(), glContext) |
- << "original GL context failed to re-bind after nested run loop, " |
- << "browser crash is imminent."; |
- glBindFramebuffer(GL_FRAMEBUFFER, previous_framebuffer); |
- } |
+ // Wait for a frame of the right size to come in, if needed. |
+ [self waitForResizedFrameInContext:glContext]; |
// If a transition to software mode has occurred, this layer should be |
// removed from the heirarchy now, so don't draw anything. |