| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/renderer_host/compositing_iosurface_layer_mac.h" | 5 #include "content/browser/renderer_host/compositing_iosurface_layer_mac.h" |
| 6 | 6 |
| 7 #include <CoreFoundation/CoreFoundation.h> | 7 #include <CoreFoundation/CoreFoundation.h> |
| 8 #include <OpenGL/gl.h> | 8 #include <OpenGL/gl.h> |
| 9 | 9 |
| 10 #include "base/mac/sdk_forward_declarations.h" | 10 #include "base/mac/sdk_forward_declarations.h" |
| 11 #include "content/browser/renderer_host/render_widget_host_impl.h" | 11 #include "content/browser/renderer_host/render_widget_host_impl.h" |
| 12 #include "content/browser/renderer_host/render_widget_host_view_mac.h" | 12 #include "content/browser/renderer_host/render_widget_host_view_mac.h" |
| 13 #include "content/browser/renderer_host/compositing_iosurface_context_mac.h" | 13 #include "content/browser/renderer_host/compositing_iosurface_context_mac.h" |
| 14 #include "content/browser/renderer_host/compositing_iosurface_mac.h" | 14 #include "content/browser/renderer_host/compositing_iosurface_mac.h" |
| 15 #include "ui/base/cocoa/animation_utils.h" | 15 #include "ui/base/cocoa/animation_utils.h" |
| 16 #include "ui/gfx/size_conversions.h" | 16 #include "ui/gfx/size_conversions.h" |
| 17 #include "ui/gl/gpu_switching_manager.h" | 17 #include "ui/gl/gpu_switching_manager.h" |
| 18 | 18 |
| 19 @interface CompositingIOSurfaceLayer() |
| 20 |
| 21 // Private method to wait for a frame of the right size if we're in an active |
| 22 // resize. This may potentially dispatch select messages from the run loop. |
| 23 - (void)waitForResizedFrameInContext:(CGLContextObj)glContext; |
| 24 |
| 25 @end |
| 26 |
| 19 @implementation CompositingIOSurfaceLayer | 27 @implementation CompositingIOSurfaceLayer |
| 20 | 28 |
| 21 @synthesize context = context_; | 29 @synthesize context = context_; |
| 22 | 30 |
| 23 - (id)initWithRenderWidgetHostViewMac:(content::RenderWidgetHostViewMac*)r { | 31 - (id)initWithRenderWidgetHostViewMac:(content::RenderWidgetHostViewMac*)r { |
| 24 if (self = [super init]) { | 32 if (self = [super init]) { |
| 25 renderWidgetHostView_ = r; | 33 renderWidgetHostView_ = r; |
| 26 context_ = content::CompositingIOSurfaceContext::Get( | 34 context_ = content::CompositingIOSurfaceContext::Get( |
| 27 content::CompositingIOSurfaceContext::kOffscreenContextWindowNumber); | 35 content::CompositingIOSurfaceContext::kOffscreenContextWindowNumber); |
| 28 DCHECK(context_); | 36 DCHECK(context_); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 | 84 |
| 77 - (void)timerSinceGotNewFrameFired { | 85 - (void)timerSinceGotNewFrameFired { |
| 78 if (![self isAsynchronous]) | 86 if (![self isAsynchronous]) |
| 79 return; | 87 return; |
| 80 | 88 |
| 81 [self setAsynchronous:NO]; | 89 [self setAsynchronous:NO]; |
| 82 if (needsDisplay_) | 90 if (needsDisplay_) |
| 83 [self setNeedsDisplay]; | 91 [self setNeedsDisplay]; |
| 84 } | 92 } |
| 85 | 93 |
| 94 - (void)waitForResizedFrameInContext:(CGLContextObj)glContext { |
| 95 // Cache a copy of renderWidgetHostView_ because it may be reset if |
| 96 // a software frame is received in GetBackingStore. |
| 97 content::RenderWidgetHostViewMac* cached_view = renderWidgetHostView_; |
| 98 if (!cached_view->render_widget_host_ || |
| 99 cached_view->render_widget_host_->is_hidden()) { |
| 100 return; |
| 101 } |
| 102 |
| 103 // Note that GetBackingStore can potentially spawn a nested run loop, which |
| 104 // may change the current GL context, or, because the GL contexts are |
| 105 // shared, may change the currently-bound FBO. Ensure that, when the run |
| 106 // loop returns, the original GL context remain current, and the original |
| 107 // FBO remain bound. |
| 108 // TODO(ccameron): This is far too fragile a mechanism to rely on. Find |
| 109 // a way to avoid doing this. |
| 110 GLuint previous_framebuffer = 0; |
| 111 glGetIntegerv(GL_FRAMEBUFFER_BINDING, |
| 112 reinterpret_cast<GLint*>(&previous_framebuffer)); |
| 113 { |
| 114 // If a resize is in progress then GetBackingStore request a frame of the |
| 115 // current window size and block until a frame of the right size comes in. |
| 116 // This makes the window content not lag behind the resize (at the cost of |
| 117 // blocking on the browser's main thread). |
| 118 gfx::ScopedCGLSetCurrentContext scoped_set_current_context(NULL); |
| 119 cached_view->about_to_validate_and_paint_ = true; |
| 120 (void)cached_view->render_widget_host_->GetBackingStore(true); |
| 121 cached_view->about_to_validate_and_paint_ = false; |
| 122 } |
| 123 CHECK_EQ(CGLGetCurrentContext(), glContext) |
| 124 << "original GL context failed to re-bind after nested run loop, " |
| 125 << "browser crash is imminent."; |
| 126 glBindFramebuffer(GL_FRAMEBUFFER, previous_framebuffer); |
| 127 } |
| 128 |
| 86 // The remaining methods implement the CAOpenGLLayer interface. | 129 // The remaining methods implement the CAOpenGLLayer interface. |
| 87 | 130 |
| 88 - (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask { | 131 - (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask { |
| 89 if (!context_) | 132 if (!context_) |
| 90 return [super copyCGLPixelFormatForDisplayMask:mask]; | 133 return [super copyCGLPixelFormatForDisplayMask:mask]; |
| 91 return CGLRetainPixelFormat(CGLGetPixelFormat(context_->cgl_context())); | 134 return CGLRetainPixelFormat(CGLGetPixelFormat(context_->cgl_context())); |
| 92 } | 135 } |
| 93 | 136 |
| 94 - (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat { | 137 - (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat { |
| 95 if (!context_) | 138 if (!context_) |
| (...skipping 21 matching lines...) Expand all Loading... |
| 117 | 160 |
| 118 if (!context_ || | 161 if (!context_ || |
| 119 (context_ && context_->cgl_context() != glContext) || | 162 (context_ && context_->cgl_context() != glContext) || |
| 120 !renderWidgetHostView_ || | 163 !renderWidgetHostView_ || |
| 121 !renderWidgetHostView_->compositing_iosurface_) { | 164 !renderWidgetHostView_->compositing_iosurface_) { |
| 122 glClearColor(1, 1, 1, 1); | 165 glClearColor(1, 1, 1, 1); |
| 123 glClear(GL_COLOR_BUFFER_BIT); | 166 glClear(GL_COLOR_BUFFER_BIT); |
| 124 return; | 167 return; |
| 125 } | 168 } |
| 126 | 169 |
| 127 // Cache a copy of renderWidgetHostView_ because it may be reset if | 170 // Acknowledge the frame before we potentially wait for a frame of the right |
| 128 // a software frame is received in GetBackingStore. | 171 // size. |
| 129 content::RenderWidgetHostViewMac* cached_view = renderWidgetHostView_; | 172 renderWidgetHostView_->SendPendingSwapAck(); |
| 130 | 173 |
| 131 // If a resize is in progress then GetBackingStore request a frame of the | 174 // Wait for a frame of the right size to come in, if needed. |
| 132 // current window size and block until a frame of the right size comes in. | 175 [self waitForResizedFrameInContext:glContext]; |
| 133 // This makes the window content not lag behind the resize (at the cost of | |
| 134 // blocking on the browser's main thread). | |
| 135 if (cached_view->render_widget_host_) { | |
| 136 // Note that GetBackingStore can potentially spawn a nested run loop, which | |
| 137 // may change the current GL context, or, because the GL contexts are | |
| 138 // shared, may change the currently-bound FBO. Ensure that, when the run | |
| 139 // loop returns, the original GL context remain current, and the original | |
| 140 // FBO remain bound. | |
| 141 // TODO(ccameron): This is far too fragile a mechanism to rely on. Find | |
| 142 // a way to avoid doing this. | |
| 143 GLuint previous_framebuffer = 0; | |
| 144 glGetIntegerv(GL_FRAMEBUFFER_BINDING, | |
| 145 reinterpret_cast<GLint*>(&previous_framebuffer)); | |
| 146 { | |
| 147 gfx::ScopedCGLSetCurrentContext scoped_set_current_context(NULL); | |
| 148 cached_view->about_to_validate_and_paint_ = true; | |
| 149 (void)cached_view->render_widget_host_->GetBackingStore(true); | |
| 150 cached_view->about_to_validate_and_paint_ = false; | |
| 151 } | |
| 152 CHECK_EQ(CGLGetCurrentContext(), glContext) | |
| 153 << "original GL context failed to re-bind after nested run loop, " | |
| 154 << "browser crash is imminent."; | |
| 155 glBindFramebuffer(GL_FRAMEBUFFER, previous_framebuffer); | |
| 156 } | |
| 157 | 176 |
| 158 // If a transition to software mode has occurred, this layer should be | 177 // If a transition to software mode has occurred, this layer should be |
| 159 // removed from the heirarchy now, so don't draw anything. | 178 // removed from the heirarchy now, so don't draw anything. |
| 160 if (!renderWidgetHostView_) | 179 if (!renderWidgetHostView_) |
| 161 return; | 180 return; |
| 162 | 181 |
| 163 gfx::Rect window_rect([self frame]); | 182 gfx::Rect window_rect([self frame]); |
| 164 float window_scale_factor = 1.f; | 183 float window_scale_factor = 1.f; |
| 165 if ([self respondsToSelector:(@selector(contentsScale))]) | 184 if ([self respondsToSelector:(@selector(contentsScale))]) |
| 166 window_scale_factor = [self contentsScale]; | 185 window_scale_factor = [self contentsScale]; |
| 167 | 186 |
| 168 if (!renderWidgetHostView_->compositing_iosurface_->DrawIOSurface( | 187 if (!renderWidgetHostView_->compositing_iosurface_->DrawIOSurface( |
| 169 context_, | 188 context_, |
| 170 window_rect, | 189 window_rect, |
| 171 window_scale_factor, | 190 window_scale_factor, |
| 172 false)) { | 191 false)) { |
| 173 renderWidgetHostView_->GotAcceleratedCompositingError(); | 192 renderWidgetHostView_->GotAcceleratedCompositingError(); |
| 174 return; | 193 return; |
| 175 } | 194 } |
| 176 | 195 |
| 177 needsDisplay_ = NO; | 196 needsDisplay_ = NO; |
| 178 renderWidgetHostView_->SendPendingLatencyInfoToHost(); | 197 renderWidgetHostView_->SendPendingLatencyInfoToHost(); |
| 179 } | 198 } |
| 180 | 199 |
| 181 @end | 200 @end |
| OLD | NEW |