| 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 <map> | 7 #include <map> |
| 8 | 8 |
| 9 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
| 10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| 11 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
| 12 #include "content/browser/compositor/gpu_process_transport_factory.h" | 12 #include "content/browser/compositor/gpu_process_transport_factory.h" |
| 13 #include "content/browser/renderer_host/compositing_iosurface_context_mac.h" | 13 #include "content/browser/compositor/software_layer_mac.h" |
| 14 #include "content/browser/renderer_host/compositing_iosurface_mac.h" | |
| 15 #include "content/browser/renderer_host/dip_util.h" | 14 #include "content/browser/renderer_host/dip_util.h" |
| 16 #include "content/browser/renderer_host/render_widget_resize_helper.h" | 15 #include "content/browser/renderer_host/render_widget_resize_helper.h" |
| 17 #include "content/browser/renderer_host/software_layer_mac.h" | |
| 18 #include "content/common/gpu/surface_handle_types_mac.h" | 16 #include "content/common/gpu/surface_handle_types_mac.h" |
| 19 #include "content/public/browser/context_factory.h" | 17 #include "content/public/browser/context_factory.h" |
| 20 #include "ui/base/cocoa/animation_utils.h" | 18 #include "ui/base/cocoa/animation_utils.h" |
| 21 #include "ui/gl/scoped_cgl.h" | 19 #include "ui/gl/scoped_cgl.h" |
| 22 | 20 |
| 23 namespace content { | 21 namespace content { |
| 24 namespace { | 22 namespace { |
| 25 | 23 |
| 26 typedef std::map<gfx::AcceleratedWidget,BrowserCompositorViewMacInternal*> | 24 typedef std::map<gfx::AcceleratedWidget,BrowserCompositorViewMacInternal*> |
| 27 WidgetToInternalsMap; | 25 WidgetToInternalsMap; |
| 28 base::LazyInstance<WidgetToInternalsMap> g_widget_to_internals_map; | 26 base::LazyInstance<WidgetToInternalsMap> g_widget_to_internals_map; |
| 29 | 27 |
| 30 } | 28 } |
| 31 | 29 |
| 32 //////////////////////////////////////////////////////////////////////////////// | 30 //////////////////////////////////////////////////////////////////////////////// |
| 33 // BrowserCompositorViewMacInternal | 31 // BrowserCompositorViewMacInternal |
| 34 | 32 |
| 35 BrowserCompositorViewMacInternal::BrowserCompositorViewMacInternal() | 33 BrowserCompositorViewMacInternal::BrowserCompositorViewMacInternal() |
| 36 : client_(NULL), | 34 : client_(NULL), |
| 37 accelerated_output_surface_id_(0) { | 35 accelerated_output_surface_id_(0), |
| 36 weak_factory_(this) { |
| 38 // Disable the fade-in animation as the layers are added. | 37 // Disable the fade-in animation as the layers are added. |
| 39 ScopedCAActionDisabler disabler; | 38 ScopedCAActionDisabler disabler; |
| 40 | 39 |
| 41 // Add a flipped transparent layer as a child, so that we don't need to | 40 // Add a flipped transparent layer as a child, so that we don't need to |
| 42 // fiddle with the position of sub-layers -- they will always be at the | 41 // fiddle with the position of sub-layers -- they will always be at the |
| 43 // origin. | 42 // origin. |
| 44 flipped_layer_.reset([[CALayer alloc] init]); | 43 flipped_layer_.reset([[CALayer alloc] init]); |
| 45 [flipped_layer_ setGeometryFlipped:YES]; | 44 [flipped_layer_ setGeometryFlipped:YES]; |
| 46 [flipped_layer_ setAnchorPoint:CGPointMake(0, 0)]; | 45 [flipped_layer_ setAnchorPoint:CGPointMake(0, 0)]; |
| 47 [flipped_layer_ | 46 [flipped_layer_ |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 103 client_ = NULL; | 102 client_ = NULL; |
| 104 } | 103 } |
| 105 | 104 |
| 106 bool BrowserCompositorViewMacInternal::HasFrameOfSize( | 105 bool BrowserCompositorViewMacInternal::HasFrameOfSize( |
| 107 const gfx::Size& dip_size) const { | 106 const gfx::Size& dip_size) const { |
| 108 return last_swap_size_dip_ == dip_size; | 107 return last_swap_size_dip_ == dip_size; |
| 109 } | 108 } |
| 110 | 109 |
| 111 int BrowserCompositorViewMacInternal::GetRendererID() const { | 110 int BrowserCompositorViewMacInternal::GetRendererID() const { |
| 112 if (io_surface_layer_) | 111 if (io_surface_layer_) |
| 113 return [io_surface_layer_ iosurface]->GetRendererID(); | 112 return [io_surface_layer_ rendererID]; |
| 114 return 0; | 113 return 0; |
| 115 } | 114 } |
| 116 | 115 |
| 117 void BrowserCompositorViewMacInternal::BeginPumpingFrames() { | 116 void BrowserCompositorViewMacInternal::BeginPumpingFrames() { |
| 118 [io_surface_layer_ beginPumpingFrames]; | 117 [io_surface_layer_ beginPumpingFrames]; |
| 119 } | 118 } |
| 120 | 119 |
| 121 void BrowserCompositorViewMacInternal::EndPumpingFrames() { | 120 void BrowserCompositorViewMacInternal::EndPumpingFrames() { |
| 122 [io_surface_layer_ endPumpingFrames]; | 121 [io_surface_layer_ endPumpingFrames]; |
| 123 } | 122 } |
| 124 | 123 |
| 125 void BrowserCompositorViewMacInternal::GotAcceleratedFrame( | 124 void BrowserCompositorViewMacInternal::GotAcceleratedFrame( |
| 126 uint64 surface_handle, int output_surface_id, | 125 uint64 surface_handle, int output_surface_id, |
| 127 const std::vector<ui::LatencyInfo>& latency_info, | 126 const std::vector<ui::LatencyInfo>& latency_info, |
| 128 gfx::Size pixel_size, float scale_factor) { | 127 gfx::Size pixel_size, float scale_factor) { |
| 129 // Record the surface and latency info to use when acknowledging this frame. | 128 // Record the surface and latency info to use when acknowledging this frame. |
| 130 DCHECK(!accelerated_output_surface_id_); | 129 DCHECK(!accelerated_output_surface_id_); |
| 131 accelerated_output_surface_id_ = output_surface_id; | 130 accelerated_output_surface_id_ = output_surface_id; |
| 132 accelerated_latency_info_.insert(accelerated_latency_info_.end(), | 131 accelerated_latency_info_.insert(accelerated_latency_info_.end(), |
| 133 latency_info.begin(), latency_info.end()); | 132 latency_info.begin(), latency_info.end()); |
| 134 | 133 |
| 135 // If there is no client and therefore no superview to draw into, early-out. | 134 // If there is no client and therefore no superview to draw into, early-out. |
| 136 if (!client_) { | 135 if (!client_) { |
| 137 AcceleratedLayerDidDrawFrame(); | 136 IOSurfaceLayerDidDrawFrame(); |
| 138 return; | 137 return; |
| 139 } | 138 } |
| 140 | 139 |
| 141 // Disable the fade-in or fade-out effect if we create or remove layers. | 140 // Disable the fade-in or fade-out effect if we create or remove layers. |
| 142 ScopedCAActionDisabler disabler; | 141 ScopedCAActionDisabler disabler; |
| 143 | 142 |
| 144 last_swap_size_dip_ = ConvertSizeToDIP(scale_factor, pixel_size); | 143 last_swap_size_dip_ = ConvertSizeToDIP(scale_factor, pixel_size); |
| 145 switch (GetSurfaceHandleType(surface_handle)) { | 144 switch (GetSurfaceHandleType(surface_handle)) { |
| 146 case kSurfaceHandleTypeIOSurface: { | 145 case kSurfaceHandleTypeIOSurface: { |
| 147 IOSurfaceID io_surface_id = IOSurfaceIDFromSurfaceHandle(surface_handle); | 146 IOSurfaceID io_surface_id = IOSurfaceIDFromSurfaceHandle(surface_handle); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 173 if ([ca_context_layer_ contextId] != ca_context_id) { | 172 if ([ca_context_layer_ contextId] != ca_context_id) { |
| 174 ca_context_layer_.reset([[CALayerHost alloc] init]); | 173 ca_context_layer_.reset([[CALayerHost alloc] init]); |
| 175 [ca_context_layer_ setContextId:ca_context_id]; | 174 [ca_context_layer_ setContextId:ca_context_id]; |
| 176 [ca_context_layer_ | 175 [ca_context_layer_ |
| 177 setAutoresizingMask:kCALayerMaxXMargin|kCALayerMaxYMargin]; | 176 setAutoresizingMask:kCALayerMaxXMargin|kCALayerMaxYMargin]; |
| 178 [flipped_layer_ addSublayer:ca_context_layer_]; | 177 [flipped_layer_ addSublayer:ca_context_layer_]; |
| 179 } | 178 } |
| 180 | 179 |
| 181 // Acknowledge the frame to unblock the compositor immediately (the GPU | 180 // Acknowledge the frame to unblock the compositor immediately (the GPU |
| 182 // process will do any required throttling). | 181 // process will do any required throttling). |
| 183 AcceleratedLayerDidDrawFrame(); | 182 IOSurfaceLayerDidDrawFrame(); |
| 184 | 183 |
| 185 // If this replacing a same-type layer, remove it now that the new layer is | 184 // If this replacing a same-type layer, remove it now that the new layer is |
| 186 // in the hierarchy. | 185 // in the hierarchy. |
| 187 if (old_ca_context_layer != ca_context_layer_) | 186 if (old_ca_context_layer != ca_context_layer_) |
| 188 DestroyCAContextLayer(old_ca_context_layer); | 187 DestroyCAContextLayer(old_ca_context_layer); |
| 189 | 188 |
| 190 // Remove any different-type layers that this is replacing. | 189 // Remove any different-type layers that this is replacing. |
| 191 DestroyIOSurfaceLayer(io_surface_layer_); | 190 DestroyIOSurfaceLayer(io_surface_layer_); |
| 192 DestroySoftwareLayer(); | 191 DestroySoftwareLayer(); |
| 193 } | 192 } |
| 194 | 193 |
| 195 void BrowserCompositorViewMacInternal::GotAcceleratedIOSurfaceFrame( | 194 void BrowserCompositorViewMacInternal::GotAcceleratedIOSurfaceFrame( |
| 196 IOSurfaceID io_surface_id, | 195 IOSurfaceID io_surface_id, |
| 197 gfx::Size pixel_size, | 196 gfx::Size pixel_size, |
| 198 float scale_factor) { | 197 float scale_factor) { |
| 199 // In the layer is replaced, keep the old one around until after the new one | 198 // In the layer is replaced, keep the old one around until after the new one |
| 200 // is installed to avoid flashes. | 199 // is installed to avoid flashes. |
| 201 base::scoped_nsobject<CompositingIOSurfaceLayer> old_io_surface_layer = | 200 base::scoped_nsobject<IOSurfaceLayer> old_io_surface_layer = |
| 202 io_surface_layer_; | 201 io_surface_layer_; |
| 203 | 202 |
| 204 // Create or re-create an IOSurface layer if needed. If there already exists | 203 // Create or re-create an IOSurface layer if needed. If there already exists |
| 205 // a layer but it has the wrong scale factor or it was poisoned, re-create the | 204 // a layer but it has the wrong scale factor re-create the layer. |
| 206 // layer. | 205 bool needs_new_layer = !io_surface_layer_ || |
| 207 bool needs_new_layer = | 206 [io_surface_layer_ scaleFactor] != scale_factor; |
| 208 !io_surface_layer_ || | |
| 209 [io_surface_layer_ context]->HasBeenPoisoned() || | |
| 210 [io_surface_layer_ iosurface]->scale_factor() != scale_factor; | |
| 211 if (needs_new_layer) { | 207 if (needs_new_layer) { |
| 212 scoped_refptr<content::CompositingIOSurfaceMac> iosurface = | 208 io_surface_layer_.reset([[IOSurfaceLayer alloc] |
| 213 content::CompositingIOSurfaceMac::Create(); | 209 initWithClient:this withScaleFactor:scale_factor]); |
| 214 if (!iosurface) { | 210 DCHECK(io_surface_layer_); |
| 215 LOG(ERROR) << "Failed to create CompositingIOSurfaceMac"; | 211 [flipped_layer_ addSublayer:io_surface_layer_]; |
| 216 } else { | |
| 217 io_surface_layer_.reset([[CompositingIOSurfaceLayer alloc] | |
| 218 initWithIOSurface:iosurface | |
| 219 withScaleFactor:scale_factor | |
| 220 withClient:this]); | |
| 221 if (io_surface_layer_) | |
| 222 [flipped_layer_ addSublayer:io_surface_layer_]; | |
| 223 else | |
| 224 LOG(ERROR) << "Failed to create CompositingIOSurfaceLayer"; | |
| 225 } | |
| 226 } | 212 } |
| 227 | 213 |
| 228 // Open the provided IOSurface. | 214 [io_surface_layer_ gotFrameWithIOSurface:io_surface_id |
| 229 if (io_surface_layer_) { | 215 withPixelSize:pixel_size |
| 230 bool result = true; | 216 withScaleFactor:scale_factor]; |
| 231 gfx::ScopedCGLSetCurrentContext scoped_set_current_context( | |
| 232 [io_surface_layer_ context]->cgl_context()); | |
| 233 result = [io_surface_layer_ iosurface]->SetIOSurfaceWithContextCurrent( | |
| 234 [io_surface_layer_ context], io_surface_id, pixel_size, scale_factor); | |
| 235 if (!result) { | |
| 236 DestroyIOSurfaceLayer(io_surface_layer_); | |
| 237 LOG(ERROR) << "Failed open IOSurface in CompositingIOSurfaceLayer"; | |
| 238 } | |
| 239 } | |
| 240 | 217 |
| 241 // Give a final complaint if anything with the layer's creation went wrong. | 218 // Set the bounds of the accelerated layer to match the size of the frame. |
| 242 // This frame will appear blank, the compositor will try to create another, | 219 // If the bounds changed, force the content to be displayed immediately. |
| 243 // and maybe that will go better. | 220 CGRect new_layer_bounds = CGRectMake( |
| 244 if (!io_surface_layer_) { | 221 0, 0, last_swap_size_dip_.width(), last_swap_size_dip_.height()); |
| 245 LOG(ERROR) << "CompositingIOSurfaceLayer is nil, tab will be blank"; | 222 bool bounds_changed = !CGRectEqualToRect( |
| 246 AcceleratedLayerHitError(); | 223 new_layer_bounds, [io_surface_layer_ bounds]); |
| 247 } | 224 [io_surface_layer_ setBounds:new_layer_bounds]; |
| 248 | 225 if (bounds_changed) |
| 249 // Make the CALayer draw and set its size appropriately. | 226 [io_surface_layer_ setNeedsDisplayAndDisplayAndAck]; |
| 250 if (io_surface_layer_) { | |
| 251 [io_surface_layer_ gotNewFrame]; | |
| 252 | |
| 253 // Set the bounds of the accelerated layer to match the size of the frame. | |
| 254 // If the bounds changed, force the content to be displayed immediately. | |
| 255 CGRect new_layer_bounds = CGRectMake( | |
| 256 0, 0, last_swap_size_dip_.width(), last_swap_size_dip_.height()); | |
| 257 bool bounds_changed = !CGRectEqualToRect( | |
| 258 new_layer_bounds, [io_surface_layer_ bounds]); | |
| 259 [io_surface_layer_ setBounds:new_layer_bounds]; | |
| 260 if (bounds_changed) | |
| 261 [io_surface_layer_ setNeedsDisplayAndDisplayAndAck]; | |
| 262 } | |
| 263 | 227 |
| 264 // If this replacing a same-type layer, remove it now that the new layer is | 228 // If this replacing a same-type layer, remove it now that the new layer is |
| 265 // in the hierarchy. | 229 // in the hierarchy. |
| 266 if (old_io_surface_layer != io_surface_layer_) | 230 if (old_io_surface_layer != io_surface_layer_) |
| 267 DestroyIOSurfaceLayer(old_io_surface_layer); | 231 DestroyIOSurfaceLayer(old_io_surface_layer); |
| 268 | 232 |
| 269 // Remove any different-type layers that this is replacing. | 233 // Remove any different-type layers that this is replacing. |
| 270 DestroyCAContextLayer(ca_context_layer_); | 234 DestroyCAContextLayer(ca_context_layer_); |
| 271 DestroySoftwareLayer(); | 235 DestroySoftwareLayer(); |
| 272 } | 236 } |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 306 void BrowserCompositorViewMacInternal::DestroyCAContextLayer( | 270 void BrowserCompositorViewMacInternal::DestroyCAContextLayer( |
| 307 base::scoped_nsobject<CALayerHost> ca_context_layer) { | 271 base::scoped_nsobject<CALayerHost> ca_context_layer) { |
| 308 if (!ca_context_layer) | 272 if (!ca_context_layer) |
| 309 return; | 273 return; |
| 310 [ca_context_layer removeFromSuperlayer]; | 274 [ca_context_layer removeFromSuperlayer]; |
| 311 if (ca_context_layer == ca_context_layer_) | 275 if (ca_context_layer == ca_context_layer_) |
| 312 ca_context_layer_.reset(); | 276 ca_context_layer_.reset(); |
| 313 } | 277 } |
| 314 | 278 |
| 315 void BrowserCompositorViewMacInternal::DestroyIOSurfaceLayer( | 279 void BrowserCompositorViewMacInternal::DestroyIOSurfaceLayer( |
| 316 base::scoped_nsobject<CompositingIOSurfaceLayer> io_surface_layer) { | 280 base::scoped_nsobject<IOSurfaceLayer> io_surface_layer) { |
| 317 if (!io_surface_layer) | 281 if (!io_surface_layer) |
| 318 return; | 282 return; |
| 319 [io_surface_layer resetClient]; | 283 [io_surface_layer resetClient]; |
| 320 [io_surface_layer removeFromSuperlayer]; | 284 [io_surface_layer removeFromSuperlayer]; |
| 321 if (io_surface_layer == io_surface_layer_) | 285 if (io_surface_layer == io_surface_layer_) |
| 322 io_surface_layer_.reset(); | 286 io_surface_layer_.reset(); |
| 323 } | 287 } |
| 324 | 288 |
| 325 void BrowserCompositorViewMacInternal::DestroySoftwareLayer() { | 289 void BrowserCompositorViewMacInternal::DestroySoftwareLayer() { |
| 326 if (!software_layer_) | 290 if (!software_layer_) |
| 327 return; | 291 return; |
| 328 [software_layer_ removeFromSuperlayer]; | 292 [software_layer_ removeFromSuperlayer]; |
| 329 software_layer_.reset(); | 293 software_layer_.reset(); |
| 330 } | 294 } |
| 331 | 295 |
| 332 bool BrowserCompositorViewMacInternal::AcceleratedLayerShouldAckImmediately() | 296 bool BrowserCompositorViewMacInternal::IOSurfaceLayerShouldAckImmediately() |
| 333 const { | 297 const { |
| 334 // If there is no client then the accelerated layer is not in the hierarchy | 298 // If there is no client then the accelerated layer is not in the hierarchy |
| 335 // and will never draw. | 299 // and will never draw. |
| 336 if (!client_) | 300 if (!client_) |
| 337 return true; | 301 return true; |
| 338 return client_->BrowserCompositorViewShouldAckImmediately(); | 302 return client_->BrowserCompositorViewShouldAckImmediately(); |
| 339 } | 303 } |
| 340 | 304 |
| 341 void BrowserCompositorViewMacInternal::AcceleratedLayerDidDrawFrame() { | 305 void BrowserCompositorViewMacInternal::IOSurfaceLayerDidDrawFrame() { |
| 342 if (accelerated_output_surface_id_) { | 306 if (accelerated_output_surface_id_) { |
| 343 content::ImageTransportFactory::GetInstance()->OnSurfaceDisplayed( | 307 content::ImageTransportFactory::GetInstance()->OnSurfaceDisplayed( |
| 344 accelerated_output_surface_id_); | 308 accelerated_output_surface_id_); |
| 345 accelerated_output_surface_id_ = 0; | 309 accelerated_output_surface_id_ = 0; |
| 346 } | 310 } |
| 347 | 311 |
| 348 if (client_) | 312 if (client_) |
| 349 client_->BrowserCompositorViewFrameSwapped(accelerated_latency_info_); | 313 client_->BrowserCompositorViewFrameSwapped(accelerated_latency_info_); |
| 350 | 314 |
| 351 accelerated_latency_info_.clear(); | 315 accelerated_latency_info_.clear(); |
| 352 } | 316 } |
| 353 | 317 |
| 354 void BrowserCompositorViewMacInternal::AcceleratedLayerHitError() { | 318 void BrowserCompositorViewMacInternal::IOSurfaceLayerHitError() { |
| 355 // Perform all acks that would have been done if the frame had succeeded, to | 319 base::MessageLoop::current()->PostTask(FROM_HERE, |
| 356 // un-block the compositor and renderer. | 320 base::Bind(&BrowserCompositorViewMacInternal::HandleIOSurfaceLayerError, |
| 357 AcceleratedLayerDidDrawFrame(); | 321 weak_factory_.GetWeakPtr())); |
| 322 } |
| 358 | 323 |
| 359 // Poison the context being used and request a mulligan. | 324 void BrowserCompositorViewMacInternal::HandleIOSurfaceLayerError() { |
| 360 if (io_surface_layer_) | 325 // Destroy the layer that caused the error. |
| 361 [io_surface_layer_ context]->PoisonContextAndSharegroup(); | 326 DestroyIOSurfaceLayer(io_surface_layer_); |
| 327 |
| 328 // Request a mulligan. |
| 362 compositor_->ScheduleFullRedraw(); | 329 compositor_->ScheduleFullRedraw(); |
| 363 } | 330 } |
| 364 | 331 |
| 365 // static | 332 // static |
| 366 BrowserCompositorViewMacInternal* BrowserCompositorViewMacInternal:: | 333 BrowserCompositorViewMacInternal* BrowserCompositorViewMacInternal:: |
| 367 FromAcceleratedWidget(gfx::AcceleratedWidget widget) { | 334 FromAcceleratedWidget(gfx::AcceleratedWidget widget) { |
| 368 WidgetToInternalsMap::const_iterator found = | 335 WidgetToInternalsMap::const_iterator found = |
| 369 g_widget_to_internals_map.Pointer()->find(widget); | 336 g_widget_to_internals_map.Pointer()->find(widget); |
| 370 // This can end up being accessed after the underlying widget has been | 337 // This can end up being accessed after the underlying widget has been |
| 371 // destroyed, but while the ui::Compositor is still being destroyed. | 338 // destroyed, but while the ui::Compositor is still being destroyed. |
| 372 // Return NULL in these cases. | 339 // Return NULL in these cases. |
| 373 if (found == g_widget_to_internals_map.Pointer()->end()) | 340 if (found == g_widget_to_internals_map.Pointer()->end()) |
| 374 return NULL; | 341 return NULL; |
| 375 return found->second; | 342 return found->second; |
| 376 } | 343 } |
| 377 | 344 |
| 378 } // namespace content | 345 } // namespace content |
| OLD | NEW |