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