Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/compositor/browser_compositor_view_private_mac.h" | 5 #include "content/browser/compositor/browser_compositor_view_private_mac.h" |
| 6 | 6 |
| 7 #include "base/debug/trace_event.h" | 7 #include "base/debug/trace_event.h" |
| 8 #include "content/browser/compositor/gpu_process_transport_factory.h" | 8 #include "content/browser/compositor/gpu_process_transport_factory.h" |
| 9 #include "content/browser/renderer_host/compositing_iosurface_context_mac.h" | 9 #include "content/browser/renderer_host/compositing_iosurface_context_mac.h" |
| 10 #include "content/browser/renderer_host/compositing_iosurface_mac.h" | 10 #include "content/browser/renderer_host/compositing_iosurface_mac.h" |
| 11 #include "content/browser/renderer_host/software_layer_mac.h" | 11 #include "content/browser/renderer_host/software_layer_mac.h" |
| 12 #include "content/public/browser/context_factory.h" | 12 #include "content/public/browser/context_factory.h" |
| 13 #include "ui/base/cocoa/animation_utils.h" | 13 #include "ui/base/cocoa/animation_utils.h" |
| 14 #include "ui/gl/scoped_cgl.h" | 14 #include "ui/gl/scoped_cgl.h" |
| 15 | 15 |
| 16 //////////////////////////////////////////////////////////////////////////////// | 16 //////////////////////////////////////////////////////////////////////////////// |
| 17 // BrowserCompositorViewCocoa | 17 // BrowserCompositorViewMacInternal |
| 18 | 18 |
| 19 @implementation BrowserCompositorViewCocoa : NSView | 19 namespace content { |
| 20 | 20 |
| 21 - (id)init { | 21 BrowserCompositorViewMacInternal::BrowserCompositorViewMacInternal() |
| 22 if (self = [super init]) { | 22 : client_(NULL), |
| 23 accelerated_layer_output_surface_id_ = 0; | 23 accelerated_layer_output_surface_id_(0) { |
| 24 client_ = NULL; | 24 // Disable the fade-in animation as the layers are added. |
| 25 helper_.reset(new content::BrowserCompositorViewCocoaHelper(self)); | 25 ScopedCAActionDisabler disabler; |
| 26 [self setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; | |
| 27 | 26 |
| 28 // Disable the fade-in animation as the layer and view are added. | 27 // Make this view host a transparent layer. |
| 29 ScopedCAActionDisabler disabler; | 28 background_layer_.reset([[CALayer alloc] init]); |
| 30 | 29 |
| 31 // Make this view host a transparent layer. | 30 // Add a flipped transparent layer as a child, so that we don't need to |
| 32 background_layer_.reset([[CALayer alloc] init]); | 31 // fiddle with the position of sub-layers -- they will always be at the |
| 33 [self setLayer:background_layer_]; | 32 // origin. |
| 34 [self setWantsLayer:YES]; | 33 flipped_layer_.reset([[CALayer alloc] init]); |
| 34 [flipped_layer_ setGeometryFlipped:YES]; | |
| 35 [flipped_layer_ | |
| 36 setAutoresizingMask:kCALayerWidthSizable|kCALayerHeightSizable]; | |
| 37 [background_layer_ addSublayer:flipped_layer_]; | |
| 35 | 38 |
| 36 // Add a flipped transparent layer as a child, so that we don't need to | 39 // Set the Cocoa view to be hosting the un-flipped background layer (hosting |
| 37 // fiddle with the position of sub-layers -- they will always be at the | 40 // a flipped layer results in unpredictable behavior). |
| 38 // origin. | 41 cocoa_view_.reset([[BrowserCompositorViewCocoa alloc] initWithClient:this]); |
| 39 flipped_layer_.reset([[CALayer alloc] init]); | 42 [cocoa_view_ setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; |
| 40 [flipped_layer_ setGeometryFlipped:YES]; | 43 [cocoa_view_ setLayer:background_layer_]; |
| 41 [flipped_layer_ | 44 [cocoa_view_ setWantsLayer:YES]; |
| 42 setAutoresizingMask:kCALayerWidthSizable|kCALayerHeightSizable]; | |
| 43 [background_layer_ addSublayer:flipped_layer_]; | |
| 44 | 45 |
| 45 compositor_.reset(new ui::Compositor(self, content::GetContextFactory())); | 46 // Create a compositor to draw the contents of |cocoa_view_|. |
| 46 } | 47 compositor_.reset(new ui::Compositor( |
| 47 return self; | 48 cocoa_view_, content::GetContextFactory())); |
| 48 } | 49 } |
| 49 | 50 |
| 50 - (void)setClient:(content::BrowserCompositorViewMacClient*)client { | 51 BrowserCompositorViewMacInternal::~BrowserCompositorViewMacInternal() { |
| 51 // Disable the fade-out as layers are removed. | 52 DCHECK(!client_); |
| 53 [cocoa_view_ resetClient]; | |
| 54 // Ensure that the compositor be destroyed before the NSView that it is | |
| 55 // using. | |
| 56 compositor_.reset(); | |
|
miu
2014/07/16 22:31:55
nit: Your choice, but you could let C++ destructio
ccameron
2014/07/17 02:30:02
Moved this to the header variable ordering.
| |
| 57 } | |
| 58 | |
| 59 void BrowserCompositorViewMacInternal::SetClient( | |
| 60 BrowserCompositorViewMacClient* client) { | |
| 61 // Disable the fade-in animation as the view is added. | |
| 52 ScopedCAActionDisabler disabler; | 62 ScopedCAActionDisabler disabler; |
| 53 [self removeFromSuperview]; | |
| 54 | 63 |
| 55 // Reset all state. | 64 DCHECK(client && !client_); |
| 65 client_ = client; | |
| 66 compositor_->SetRootLayer(client_->BrowserCompositorRootLayer()); | |
| 67 [cocoa_view_ setFrame:[client_->BrowserCompositorSuperview() frame]]; | |
| 68 [client_->BrowserCompositorSuperview() addSubview:cocoa_view_]; | |
| 69 } | |
| 70 | |
| 71 void BrowserCompositorViewMacInternal::ResetClient() { | |
| 72 if (!client_) | |
| 73 return; | |
| 74 | |
| 75 // Disable the fade-out animation as the view is removed. | |
| 76 ScopedCAActionDisabler disabler; | |
| 77 | |
| 78 [cocoa_view_ removeFromSuperview]; | |
| 79 | |
| 56 [accelerated_layer_ removeFromSuperlayer]; | 80 [accelerated_layer_ removeFromSuperlayer]; |
| 57 [accelerated_layer_ resetClient]; | 81 [accelerated_layer_ resetClient]; |
| 58 accelerated_layer_.reset(); | 82 accelerated_layer_.reset(); |
| 59 accelerated_layer_output_surface_id_ = 0; | 83 accelerated_layer_output_surface_id_ = 0; |
| 84 | |
| 60 [software_layer_ removeFromSuperlayer]; | 85 [software_layer_ removeFromSuperlayer]; |
| 61 software_layer_.reset(); | 86 software_layer_.reset(); |
| 87 | |
| 62 compositor_->SetScaleAndSize(1.0, gfx::Size(0, 0)); | 88 compositor_->SetScaleAndSize(1.0, gfx::Size(0, 0)); |
| 63 | 89 compositor_->SetRootLayer(NULL); |
| 64 client_ = client; | 90 client_ = NULL; |
| 65 if (client_) { | |
| 66 DCHECK(compositor_); | |
| 67 compositor_->SetRootLayer(client_->BrowserCompositorRootLayer()); | |
| 68 [self setFrame:[client_->BrowserCompositorSuperview() frame]]; | |
| 69 [client_->BrowserCompositorSuperview() addSubview:self]; | |
| 70 } else { | |
| 71 compositor_->SetRootLayer(NULL); | |
| 72 } | |
| 73 } | 91 } |
| 74 | 92 |
| 75 - (void)destroyCompositor { | 93 void BrowserCompositorViewMacInternal::GotAcceleratedIOSurfaceFrame( |
| 76 DCHECK(!client_); | 94 IOSurfaceID io_surface_id, |
| 77 compositor_.reset(); | 95 int output_surface_id, |
| 78 } | 96 const std::vector<ui::LatencyInfo>& latency_info, |
| 79 | 97 gfx::Size pixel_size, |
| 80 - (void)gotAcceleratedLayerError { | 98 float scale_factor) { |
| 81 if (!accelerated_layer_) | |
| 82 return; | |
| 83 | |
| 84 [accelerated_layer_ context]->PoisonContextAndSharegroup(); | |
| 85 compositor_->ScheduleFullRedraw(); | |
| 86 } | |
| 87 | |
| 88 - (ui::Compositor*)compositor { | |
| 89 return compositor_.get(); | |
| 90 } | |
| 91 | |
| 92 - (void)gotAcceleratedIOSurfaceFrame:(IOSurfaceID)surface_handle | |
| 93 withOutputSurfaceID:(int)surface_id | |
| 94 withLatencyInfo:(std::vector<ui::LatencyInfo>) latency_info | |
| 95 withPixelSize:(gfx::Size)pixel_size | |
| 96 withScaleFactor:(float)scale_factor { | |
| 97 DCHECK(!accelerated_layer_output_surface_id_); | 99 DCHECK(!accelerated_layer_output_surface_id_); |
| 98 accelerated_layer_output_surface_id_ = surface_id; | 100 accelerated_layer_output_surface_id_ = output_surface_id; |
| 99 accelerated_latency_info_.insert(accelerated_latency_info_.end(), | 101 accelerated_latency_info_.insert(accelerated_latency_info_.end(), |
| 100 latency_info.begin(), latency_info.end()); | 102 latency_info.begin(), latency_info.end()); |
| 101 | 103 |
| 104 // If there is no client and therefore no superview to draw into, early-out. | |
| 105 if (!client_) { | |
| 106 AcceleratedLayerDidDrawFrame(true); | |
| 107 return; | |
| 108 } | |
| 109 | |
| 110 // Disable the fade-in or fade-out effect if we create or remove layers. | |
| 102 ScopedCAActionDisabler disabler; | 111 ScopedCAActionDisabler disabler; |
| 103 | 112 |
| 104 // If there is already an accelerated layer, but it has the wrong scale | 113 // If there is already an accelerated layer, but it has the wrong scale |
| 105 // factor or it was poisoned, remove the old layer and replace it. | 114 // factor or it was poisoned, remove the old layer and replace it. |
| 106 base::scoped_nsobject<CompositingIOSurfaceLayer> old_accelerated_layer; | 115 base::scoped_nsobject<CompositingIOSurfaceLayer> old_accelerated_layer; |
| 107 if (accelerated_layer_ && ( | 116 if (accelerated_layer_ && ( |
| 108 [accelerated_layer_ context]->HasBeenPoisoned() || | 117 [accelerated_layer_ context]->HasBeenPoisoned() || |
| 109 [accelerated_layer_ iosurface]->scale_factor() != scale_factor)) { | 118 [accelerated_layer_ iosurface]->scale_factor() != scale_factor)) { |
| 110 old_accelerated_layer = accelerated_layer_; | 119 old_accelerated_layer = accelerated_layer_; |
| 111 accelerated_layer_.reset(); | 120 accelerated_layer_.reset(); |
| 112 } | 121 } |
| 113 | 122 |
| 114 // If there is not a layer for accelerated frames, create one. | 123 // If there is not a layer for accelerated frames, create one. |
| 115 if (!accelerated_layer_) { | 124 if (!accelerated_layer_) { |
| 116 // Disable the fade-in animation as the layer is added. | |
| 117 ScopedCAActionDisabler disabler; | |
| 118 scoped_refptr<content::CompositingIOSurfaceMac> iosurface = | 125 scoped_refptr<content::CompositingIOSurfaceMac> iosurface = |
| 119 content::CompositingIOSurfaceMac::Create(); | 126 content::CompositingIOSurfaceMac::Create(); |
| 120 accelerated_layer_.reset([[CompositingIOSurfaceLayer alloc] | 127 accelerated_layer_.reset([[CompositingIOSurfaceLayer alloc] |
| 121 initWithIOSurface:iosurface | 128 initWithIOSurface:iosurface |
| 122 withScaleFactor:scale_factor | 129 withScaleFactor:scale_factor |
| 123 withClient:helper_.get()]); | 130 withClient:this]); |
| 124 [flipped_layer_ addSublayer:accelerated_layer_]; | 131 [flipped_layer_ addSublayer:accelerated_layer_]; |
| 125 } | 132 } |
| 126 | 133 |
| 134 // Open the provided IOSurface. | |
| 127 { | 135 { |
| 128 bool result = true; | 136 bool result = true; |
| 129 gfx::ScopedCGLSetCurrentContext scoped_set_current_context( | 137 gfx::ScopedCGLSetCurrentContext scoped_set_current_context( |
| 130 [accelerated_layer_ context]->cgl_context()); | 138 [accelerated_layer_ context]->cgl_context()); |
| 131 result = [accelerated_layer_ iosurface]->SetIOSurfaceWithContextCurrent( | 139 result = [accelerated_layer_ iosurface]->SetIOSurfaceWithContextCurrent( |
| 132 [accelerated_layer_ context], surface_handle, pixel_size, scale_factor); | 140 [accelerated_layer_ context], io_surface_id, pixel_size, scale_factor); |
| 133 if (!result) | 141 if (!result) |
| 134 LOG(ERROR) << "Failed SetIOSurface on CompositingIOSurfaceMac"; | 142 LOG(ERROR) << "Failed SetIOSurface on CompositingIOSurfaceMac"; |
| 135 } | 143 } |
| 136 [accelerated_layer_ gotNewFrame]; | 144 [accelerated_layer_ gotNewFrame]; |
| 137 | 145 |
| 138 // Set the bounds of the accelerated layer to match the size of the frame. | 146 // Set the bounds of the accelerated layer to match the size of the frame. |
| 139 // If the bounds changed, force the content to be displayed immediately. | 147 // If the bounds changed, force the content to be displayed immediately. |
| 140 CGRect new_layer_bounds = CGRectMake( | 148 CGRect new_layer_bounds = CGRectMake( |
| 141 0, | 149 0, |
| 142 0, | 150 0, |
| 143 [accelerated_layer_ iosurface]->dip_io_surface_size().width(), | 151 [accelerated_layer_ iosurface]->dip_io_surface_size().width(), |
| 144 [accelerated_layer_ iosurface]->dip_io_surface_size().height()); | 152 [accelerated_layer_ iosurface]->dip_io_surface_size().height()); |
| 145 bool bounds_changed = !CGRectEqualToRect( | 153 bool bounds_changed = !CGRectEqualToRect( |
| 146 new_layer_bounds, [accelerated_layer_ bounds]); | 154 new_layer_bounds, [accelerated_layer_ bounds]); |
| 147 [accelerated_layer_ setBounds:new_layer_bounds]; | 155 [accelerated_layer_ setBounds:new_layer_bounds]; |
| 148 if (bounds_changed) { | 156 if (bounds_changed) { |
| 149 [accelerated_layer_ setNeedsDisplay]; | 157 [accelerated_layer_ setNeedsDisplay]; |
| 150 [accelerated_layer_ displayIfNeeded]; | 158 [accelerated_layer_ displayIfNeeded]; |
| 151 } | 159 } |
| 152 | 160 |
| 153 // If there was a software layer or an old accelerated layer, remove it. | 161 // If there was a software layer or an old accelerated layer, remove it. |
| 154 // Disable the fade-out animation as the layer is removed. | 162 // Disable the fade-out animation as the layer is removed. |
| 155 { | 163 { |
| 156 ScopedCAActionDisabler disabler; | |
| 157 [software_layer_ removeFromSuperlayer]; | 164 [software_layer_ removeFromSuperlayer]; |
| 158 software_layer_.reset(); | 165 software_layer_.reset(); |
| 159 [old_accelerated_layer resetClient]; | 166 [old_accelerated_layer resetClient]; |
| 160 [old_accelerated_layer removeFromSuperlayer]; | 167 [old_accelerated_layer removeFromSuperlayer]; |
| 161 old_accelerated_layer.reset(); | 168 old_accelerated_layer.reset(); |
| 162 } | 169 } |
| 163 } | 170 } |
| 164 | 171 |
| 165 - (void)gotSoftwareFrame:(cc::SoftwareFrameData*)frame_data | 172 void BrowserCompositorViewMacInternal::GotSoftwareFrame( |
| 166 withScaleFactor:(float)scale_factor | 173 cc::SoftwareFrameData* frame_data, |
| 167 withCanvas:(SkCanvas*)canvas { | 174 float scale_factor, |
| 168 if (!frame_data || !canvas) | 175 SkCanvas* canvas) { |
| 176 if (!frame_data || !canvas || !client_) | |
| 169 return; | 177 return; |
| 170 | 178 |
| 179 // Disable the fade-in or fade-out effect if we create or remove layers. | |
| 180 ScopedCAActionDisabler disabler; | |
| 181 | |
| 171 // If there is not a layer for software frames, create one. | 182 // If there is not a layer for software frames, create one. |
| 172 if (!software_layer_) { | 183 if (!software_layer_) { |
| 173 // Disable the fade-in animation as the layer is added. | |
| 174 ScopedCAActionDisabler disabler; | |
| 175 software_layer_.reset([[SoftwareLayer alloc] init]); | 184 software_layer_.reset([[SoftwareLayer alloc] init]); |
| 176 [flipped_layer_ addSublayer:software_layer_]; | 185 [flipped_layer_ addSublayer:software_layer_]; |
| 177 } | 186 } |
| 178 | 187 |
| 188 // Set the software layer to draw the provided canvas. | |
| 179 SkImageInfo info; | 189 SkImageInfo info; |
| 180 size_t row_bytes; | 190 size_t row_bytes; |
| 181 const void* pixels = canvas->peekPixels(&info, &row_bytes); | 191 const void* pixels = canvas->peekPixels(&info, &row_bytes); |
| 182 [software_layer_ setContentsToData:pixels | 192 [software_layer_ setContentsToData:pixels |
| 183 withRowBytes:row_bytes | 193 withRowBytes:row_bytes |
| 184 withPixelSize:gfx::Size(info.fWidth, info.fHeight) | 194 withPixelSize:gfx::Size(info.fWidth, info.fHeight) |
| 185 withScaleFactor:scale_factor]; | 195 withScaleFactor:scale_factor]; |
| 186 | 196 |
| 187 // If there was an accelerated layer, remove it. | 197 // If there was an accelerated layer, remove it. |
| 188 // Disable the fade-out animation as the layer is removed. | |
| 189 { | 198 { |
| 190 ScopedCAActionDisabler disabler; | |
| 191 [accelerated_layer_ resetClient]; | 199 [accelerated_layer_ resetClient]; |
| 192 [accelerated_layer_ removeFromSuperlayer]; | 200 [accelerated_layer_ removeFromSuperlayer]; |
| 193 accelerated_layer_.reset(); | 201 accelerated_layer_.reset(); |
| 194 } | 202 } |
| 195 | |
| 196 // This call can be nested insider ui::Compositor commit calls, and can also | |
| 197 // make additional ui::Compositor commit calls. Avoid the potential recursion | |
| 198 // by acknowledging the frame asynchronously. | |
| 199 [self performSelector:@selector(layerDidDrawFrame) | |
| 200 withObject:nil | |
| 201 afterDelay:0]; | |
| 202 } | 203 } |
| 203 | 204 |
| 204 - (void)layerDidDrawFrame { | 205 void BrowserCompositorViewMacInternal::AcceleratedLayerDidDrawFrame( |
| 206 bool succeeded) { | |
| 205 if (accelerated_layer_output_surface_id_) { | 207 if (accelerated_layer_output_surface_id_) { |
| 206 content::ImageTransportFactory::GetInstance()->OnSurfaceDisplayed( | 208 content::ImageTransportFactory::GetInstance()->OnSurfaceDisplayed( |
| 207 accelerated_layer_output_surface_id_); | 209 accelerated_layer_output_surface_id_); |
| 208 accelerated_layer_output_surface_id_ = 0; | 210 accelerated_layer_output_surface_id_ = 0; |
| 209 } | 211 } |
| 210 | 212 |
| 211 if (client_) | 213 if (client_) |
| 212 client_->BrowserCompositorViewFrameSwapped(accelerated_latency_info_); | 214 client_->BrowserCompositorViewFrameSwapped(accelerated_latency_info_); |
| 215 | |
| 213 accelerated_latency_info_.clear(); | 216 accelerated_latency_info_.clear(); |
| 217 | |
| 218 if (!succeeded) { | |
| 219 if (accelerated_layer_) | |
| 220 [accelerated_layer_ context]->PoisonContextAndSharegroup(); | |
| 221 compositor_->ScheduleFullRedraw(); | |
| 222 } | |
| 223 } | |
| 224 | |
| 225 } // namespace content | |
| 226 | |
| 227 //////////////////////////////////////////////////////////////////////////////// | |
| 228 // BrowserCompositorViewCocoa | |
| 229 | |
| 230 @implementation BrowserCompositorViewCocoa | |
| 231 | |
| 232 - (id)initWithClient:(content::BrowserCompositorViewCocoaClient*)client { | |
| 233 if (self = [super init]) { | |
| 234 client_ = client; | |
| 235 } | |
| 236 return self; | |
| 237 } | |
| 238 | |
| 239 - (void)dealloc { | |
| 240 DCHECK(!client_); | |
| 241 [super dealloc]; | |
| 242 } | |
| 243 | |
| 244 - (void)resetClient { | |
| 245 client_ = NULL; | |
| 246 } | |
| 247 | |
| 248 - (void)gotAcceleratedIOSurfaceFrame:(IOSurfaceID)surface_handle | |
| 249 withOutputSurfaceID:(int)surface_id | |
| 250 withLatencyInfo:(std::vector<ui::LatencyInfo>)latency_info | |
| 251 withPixelSize:(gfx::Size)pixel_size | |
| 252 withScaleFactor:(float)scale_factor { | |
| 253 if (!client_) | |
| 254 return; | |
| 255 client_->GotAcceleratedIOSurfaceFrame( | |
| 256 surface_handle, surface_id, latency_info, pixel_size, scale_factor); | |
| 257 } | |
| 258 | |
| 259 - (void)gotSoftwareFrame:(cc::SoftwareFrameData*)frame_data | |
| 260 withScaleFactor:(float)scale_factor | |
| 261 withCanvas:(SkCanvas*)canvas { | |
| 262 if (!client_) | |
| 263 return; | |
| 264 client_->GotSoftwareFrame(frame_data, scale_factor, canvas); | |
| 214 } | 265 } |
| 215 | 266 |
| 216 @end // BrowserCompositorViewCocoa | 267 @end // BrowserCompositorViewCocoa |
| 217 | 268 |
| 218 //////////////////////////////////////////////////////////////////////////////// | |
| 219 // BrowserCompositorViewCocoaHelper | |
| 220 | |
| 221 namespace content { | |
| 222 | |
| 223 void BrowserCompositorViewCocoaHelper::AcceleratedLayerDidDrawFrame( | |
| 224 bool succeeded) { | |
| 225 [view_ layerDidDrawFrame]; | |
| 226 if (!succeeded) | |
| 227 [view_ gotAcceleratedLayerError]; | |
| 228 } | |
| 229 | |
| 230 } | |
| 231 | |
| OLD | NEW |