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 |