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 |