Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(144)

Side by Side Diff: ui/accelerated_widget_mac/accelerated_widget_mac.mm

Issue 1420533005: Mac: Kill lots of AcceleratedWidget code (with fire) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix native build Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "ui/accelerated_widget_mac/accelerated_widget_mac.h" 5 #include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
6 6
7 #include <map> 7 #include <map>
8 8
9 #include "base/lazy_instance.h" 9 #include "base/lazy_instance.h"
10 #include "base/mac/scoped_cftyperef.h"
10 #include "base/message_loop/message_loop.h" 11 #include "base/message_loop/message_loop.h"
11 #include "base/trace_event/trace_event.h" 12 #include "base/trace_event/trace_event.h"
12 #include "third_party/skia/include/core/SkCanvas.h" 13 #include "third_party/skia/include/core/SkCanvas.h"
13 #include "ui/accelerated_widget_mac/io_surface_layer.h"
14 #include "ui/accelerated_widget_mac/surface_handle_types.h" 14 #include "ui/accelerated_widget_mac/surface_handle_types.h"
15 #include "ui/base/cocoa/animation_utils.h" 15 #include "ui/base/cocoa/animation_utils.h"
16 #include "ui/gfx/geometry/dip_util.h" 16 #include "ui/gfx/geometry/dip_util.h"
17 #include "ui/gl/scoped_cgl.h" 17 #include "ui/gl/scoped_cgl.h"
18 18
19 @interface CALayer (Private)
tapted 2015/10/22 08:26:50 nit: Private -> PrivateAPI ("Private" could also
ccameron 2015/10/22 19:26:11 Done.
20 - (void)setContentsChanged;
21 @end
22
19 namespace ui { 23 namespace ui {
20 namespace { 24 namespace {
21 25
22 typedef std::map<gfx::AcceleratedWidget,AcceleratedWidgetMac*> 26 typedef std::map<gfx::AcceleratedWidget,AcceleratedWidgetMac*>
23 WidgetToHelperMap; 27 WidgetToHelperMap;
24 base::LazyInstance<WidgetToHelperMap> g_widget_to_helper_map; 28 base::LazyInstance<WidgetToHelperMap> g_widget_to_helper_map;
25 29
26 AcceleratedWidgetMac* GetHelperFromAcceleratedWidget( 30 AcceleratedWidgetMac* GetHelperFromAcceleratedWidget(
27 gfx::AcceleratedWidget widget) { 31 gfx::AcceleratedWidget widget) {
28 WidgetToHelperMap::const_iterator found = 32 WidgetToHelperMap::const_iterator found =
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 } 88 }
85 89
86 void AcceleratedWidgetMac::ResetNSView() { 90 void AcceleratedWidgetMac::ResetNSView() {
87 if (!view_) 91 if (!view_)
88 return; 92 return;
89 93
90 // Disable the fade-out animation as the view is removed. 94 // Disable the fade-out animation as the view is removed.
91 ScopedCAActionDisabler disabler; 95 ScopedCAActionDisabler disabler;
92 96
93 [flipped_layer_ removeFromSuperlayer]; 97 [flipped_layer_ removeFromSuperlayer];
94 DestroyIOSurfaceLayer(io_surface_layer_);
95 DestroyCAContextLayer(ca_context_layer_); 98 DestroyCAContextLayer(ca_context_layer_);
96 DestroySoftwareLayer(); 99 DestroyLocalLayer();
97 100
98 last_swap_size_dip_ = gfx::Size(); 101 last_swap_size_dip_ = gfx::Size();
99 view_ = NULL; 102 view_ = NULL;
100 } 103 }
101 104
102 bool AcceleratedWidgetMac::HasFrameOfSize( 105 bool AcceleratedWidgetMac::HasFrameOfSize(
103 const gfx::Size& dip_size) const { 106 const gfx::Size& dip_size) const {
104 return last_swap_size_dip_ == dip_size; 107 return last_swap_size_dip_ == dip_size;
105 } 108 }
106 109
107 int AcceleratedWidgetMac::GetRendererID() const { 110 int AcceleratedWidgetMac::GetRendererID() const {
108 if (io_surface_layer_)
109 return [io_surface_layer_ rendererID];
110 return 0; 111 return 0;
111 } 112 }
112 113
113 void AcceleratedWidgetMac::GetVSyncParameters( 114 void AcceleratedWidgetMac::GetVSyncParameters(
114 base::TimeTicks* timebase, base::TimeDelta* interval) const { 115 base::TimeTicks* timebase, base::TimeDelta* interval) const {
115 if (view_) { 116 if (view_) {
116 view_->AcceleratedWidgetGetVSyncParameters(timebase, interval); 117 view_->AcceleratedWidgetGetVSyncParameters(timebase, interval);
117 } else { 118 } else {
118 *timebase = base::TimeTicks(); 119 *timebase = base::TimeTicks();
119 *interval = base::TimeDelta(); 120 *interval = base::TimeDelta();
120 } 121 }
121 } 122 }
122 123
123 bool AcceleratedWidgetMac::IsRendererThrottlingDisabled() const { 124 bool AcceleratedWidgetMac::IsRendererThrottlingDisabled() const {
124 if (view_) 125 if (view_)
125 return view_->AcceleratedWidgetShouldIgnoreBackpressure(); 126 return view_->AcceleratedWidgetShouldIgnoreBackpressure();
126 return false; 127 return false;
127 } 128 }
128 129
129 void AcceleratedWidgetMac::BeginPumpingFrames() { 130 void AcceleratedWidgetMac::BeginPumpingFrames() {
130 [io_surface_layer_ beginPumpingFrames];
131 } 131 }
132 132
133 void AcceleratedWidgetMac::EndPumpingFrames() { 133 void AcceleratedWidgetMac::EndPumpingFrames() {
134 [io_surface_layer_ endPumpingFrames];
135 } 134 }
136 135
137 void AcceleratedWidgetMac::GotAcceleratedFrame( 136 void AcceleratedWidgetMac::GotAcceleratedFrame(
138 uint64 surface_handle, 137 uint64 surface_handle,
139 const std::vector<ui::LatencyInfo>& latency_info, 138 const std::vector<ui::LatencyInfo>& latency_info,
140 const gfx::Size& pixel_size, 139 const gfx::Size& pixel_size,
141 float scale_factor, 140 float scale_factor,
142 const gfx::Rect& pixel_damage_rect, 141 const gfx::Rect& pixel_damage_rect,
143 const base::Closure& drawn_callback) { 142 const base::Closure& drawn_callback) {
144 // Record the surface and latency info to use when acknowledging this frame. 143 // Record the surface and latency info to use when acknowledging this frame.
(...skipping 20 matching lines...) Expand all
165 } 164 }
166 case kSurfaceHandleTypeCAContext: { 165 case kSurfaceHandleTypeCAContext: {
167 CAContextID ca_context_id = CAContextIDFromSurfaceHandle(surface_handle); 166 CAContextID ca_context_id = CAContextIDFromSurfaceHandle(surface_handle);
168 GotAcceleratedCAContextFrame(ca_context_id, pixel_size, scale_factor); 167 GotAcceleratedCAContextFrame(ca_context_id, pixel_size, scale_factor);
169 break; 168 break;
170 } 169 }
171 default: 170 default:
172 LOG(ERROR) << "Unrecognized accelerated frame type."; 171 LOG(ERROR) << "Unrecognized accelerated frame type.";
173 return; 172 return;
174 } 173 }
174
175 AcknowledgeAcceleratedFrame();
175 } 176 }
176 177
177 void AcceleratedWidgetMac::GotAcceleratedCAContextFrame( 178 void AcceleratedWidgetMac::GotAcceleratedCAContextFrame(
178 CAContextID ca_context_id, 179 CAContextID ca_context_id,
179 const gfx::Size& pixel_size, 180 const gfx::Size& pixel_size,
180 float scale_factor) { 181 float scale_factor) {
181 // In the layer is replaced, keep the old one around until after the new one 182 // In the layer is replaced, keep the old one around until after the new one
182 // is installed to avoid flashes. 183 // is installed to avoid flashes.
183 base::scoped_nsobject<CALayerHost> old_ca_context_layer = 184 base::scoped_nsobject<CALayerHost> old_ca_context_layer =
184 ca_context_layer_; 185 ca_context_layer_;
185 186
186 // Create the layer to host the layer exported by the GPU process with this 187 // Create the layer to host the layer exported by the GPU process with this
187 // particular CAContext ID. 188 // particular CAContext ID.
188 if ([ca_context_layer_ contextId] != ca_context_id) { 189 if ([ca_context_layer_ contextId] != ca_context_id) {
189 ca_context_layer_.reset([[CALayerHost alloc] init]); 190 ca_context_layer_.reset([[CALayerHost alloc] init]);
190 [ca_context_layer_ setContextId:ca_context_id]; 191 [ca_context_layer_ setContextId:ca_context_id];
191 [ca_context_layer_ 192 [ca_context_layer_
192 setAutoresizingMask:kCALayerMaxXMargin|kCALayerMaxYMargin]; 193 setAutoresizingMask:kCALayerMaxXMargin|kCALayerMaxYMargin];
193 [flipped_layer_ addSublayer:ca_context_layer_]; 194 [flipped_layer_ addSublayer:ca_context_layer_];
194 } 195 }
195 196
196 // Acknowledge the frame to unblock the compositor immediately (the GPU
197 // process will do any required throttling).
198 AcknowledgeAcceleratedFrame();
199
200 // If this replacing a same-type layer, remove it now that the new layer is 197 // If this replacing a same-type layer, remove it now that the new layer is
201 // in the hierarchy. 198 // in the hierarchy.
202 if (old_ca_context_layer != ca_context_layer_) 199 if (old_ca_context_layer != ca_context_layer_)
203 DestroyCAContextLayer(old_ca_context_layer); 200 DestroyCAContextLayer(old_ca_context_layer);
204 201
205 // Remove any different-type layers that this is replacing. 202 // Remove any different-type layers that this is replacing.
206 DestroyIOSurfaceLayer(io_surface_layer_); 203 DestroyLocalLayer();
207 DestroySoftwareLayer();
208 } 204 }
209 205
210 void AcceleratedWidgetMac::GotAcceleratedIOSurfaceFrame( 206 void AcceleratedWidgetMac::GotAcceleratedIOSurfaceFrame(
211 IOSurfaceID io_surface_id, 207 IOSurfaceID io_surface_id,
212 const gfx::Size& pixel_size, 208 const gfx::Size& pixel_size,
213 float scale_factor) { 209 float scale_factor) {
214 // In the layer is replaced, keep the old one around until after the new one 210 base::ScopedCFTypeRef<IOSurfaceRef> io_surface(
215 // is installed to avoid flashes. 211 IOSurfaceLookup(io_surface_id));
216 base::scoped_nsobject<IOSurfaceLayer> old_io_surface_layer = 212 GotIOSurfaceFrame(io_surface, pixel_size, scale_factor, true);
217 io_surface_layer_; 213 }
218 214
219 // Create or re-create an IOSurface layer if needed. If there already exists 215 void AcceleratedWidgetMac::EnsureLocalLayer() {
220 // a layer but it has the wrong scale factor or it was poisoned, re-create the 216 if (!local_layer_) {
221 // layer. 217 local_layer_.reset([[CALayer alloc] init]);
222 bool needs_new_layer = 218 // Setting contents gravity is necessary to prevent the layer from being
223 !io_surface_layer_ || 219 // scaled during dyanmic resizes (especially with devtools open).
224 [io_surface_layer_ hasBeenPoisoned] || 220 [local_layer_ setContentsGravity:kCAGravityTopLeft];
225 [io_surface_layer_ scaleFactor] != scale_factor; 221 [flipped_layer_ addSublayer:local_layer_];
226 if (needs_new_layer) { 222 }
227 io_surface_layer_.reset( 223 }
228 [[IOSurfaceLayer alloc] initWithClient:this 224
229 withScaleFactor:scale_factor 225 void AcceleratedWidgetMac::GotIOSurfaceFrame(
230 needsGLFinishWorkaround:needs_gl_finish_workaround_]); 226 base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
231 if (io_surface_layer_) 227 const gfx::Size& pixel_size,
232 [flipped_layer_ addSublayer:io_surface_layer_]; 228 float scale_factor,
233 else 229 bool flip_y) {
234 LOG(ERROR) << "Failed to create IOSurfaceLayer"; 230 // Disable the fade-in or fade-out effect if we create or remove layers.
231 ScopedCAActionDisabler disabler;
232
233 // If there is not a layer for local frames, create one.
234 EnsureLocalLayer();
235
236 id new_contents = io_surface.get() ? static_cast<id>(io_surface.get()) : nil;
237
238 if (new_contents && new_contents == [local_layer_ contents]) {
239 [local_layer_ setContentsChanged];
240 } else {
241 [local_layer_ setContents:new_contents];
235 } 242 }
236 243
237 // Open the provided IOSurface. 244 [local_layer_ setBounds:CGRectMake(0, 0, pixel_size.width() / scale_factor,
238 if (io_surface_layer_) { 245 pixel_size.height() / scale_factor)];
239 bool result = [io_surface_layer_ gotFrameWithIOSurface:io_surface_id 246
240 withPixelSize:pixel_size 247 if ([local_layer_ respondsToSelector:(@selector(contentsScale))] &&
241 withScaleFactor:scale_factor]; 248 [local_layer_ respondsToSelector:(@selector(setContentsScale:))] &&
242 if (!result) { 249 [local_layer_ contentsScale] != scale_factor) {
243 DestroyIOSurfaceLayer(io_surface_layer_); 250 [local_layer_ setContentsScale:scale_factor];
244 LOG(ERROR) << "Failed open IOSurface in IOSurfaceLayer";
245 }
246 } 251 }
247 252
248 // Give a final complaint if anything with the layer's creation went wrong. 253 if (flip_y) {
249 // This frame will appear blank, the compositor will try to create another, 254 [local_layer_ setAnchorPoint:CGPointMake(0, 1)];
250 // and maybe that will go better. 255 [local_layer_ setAffineTransform:CGAffineTransformMakeScale(1.0, -1.0)];
251 if (!io_surface_layer_) { 256 } else {
252 LOG(ERROR) << "IOSurfaceLayer is nil, tab will be blank"; 257 [local_layer_ setAnchorPoint:CGPointMake(0, 0)];
253 IOSurfaceLayerHitError(); 258 [local_layer_ setAffineTransform:CGAffineTransformMakeScale(1.0, 1.0)];
254 } 259 }
255 260
256 // Make the CALayer draw and set its size appropriately.
257 if (io_surface_layer_) {
258 [io_surface_layer_ gotNewFrame];
259
260 // Set the bounds of the accelerated layer to match the size of the frame.
261 // If the bounds changed, force the content to be displayed immediately.
262 CGRect new_layer_bounds = CGRectMake(
263 0, 0, last_swap_size_dip_.width(), last_swap_size_dip_.height());
264 bool bounds_changed = !CGRectEqualToRect(
265 new_layer_bounds, [io_surface_layer_ bounds]);
266 [io_surface_layer_ setBounds:new_layer_bounds];
267 if (bounds_changed)
268 [io_surface_layer_ setNeedsDisplayAndDisplayAndAck];
269 }
270
271 // If this replacing a same-type layer, remove it now that the new layer is
272 // in the hierarchy.
273 if (old_io_surface_layer != io_surface_layer_)
274 DestroyIOSurfaceLayer(old_io_surface_layer);
275
276 // Remove any different-type layers that this is replacing. 261 // Remove any different-type layers that this is replacing.
277 DestroyCAContextLayer(ca_context_layer_); 262 DestroyCAContextLayer(ca_context_layer_);
278 DestroySoftwareLayer();
279 }
280
281 void AcceleratedWidgetMac::GotSoftwareFrame(float scale_factor,
282 SkCanvas* canvas) {
283 if (!canvas || !view_)
284 return;
285
286 // Disable the fade-in or fade-out effect if we create or remove layers.
287 ScopedCAActionDisabler disabler;
288
289 // If there is not a layer for software frames, create one.
290 if (!software_layer_) {
291 software_layer_.reset([[SoftwareLayer alloc] init]);
292 [flipped_layer_ addSublayer:software_layer_];
293 }
294
295 // Set the software layer to draw the provided canvas.
296 SkImageInfo info;
297 size_t row_bytes;
298 const void* pixels = canvas->peekPixels(&info, &row_bytes);
299 gfx::Size pixel_size(info.width(), info.height());
300 [software_layer_ setContentsToData:pixels
301 withRowBytes:row_bytes
302 withPixelSize:pixel_size
303 withScaleFactor:scale_factor];
304 last_swap_size_dip_ = gfx::ConvertSizeToDIP(scale_factor, pixel_size);
305
306 // Remove any different-type layers that this is replacing.
307 DestroyCAContextLayer(ca_context_layer_);
308 DestroyIOSurfaceLayer(io_surface_layer_);
309 } 263 }
310 264
311 void AcceleratedWidgetMac::DestroyCAContextLayer( 265 void AcceleratedWidgetMac::DestroyCAContextLayer(
312 base::scoped_nsobject<CALayerHost> ca_context_layer) { 266 base::scoped_nsobject<CALayerHost> ca_context_layer) {
313 if (!ca_context_layer) 267 if (!ca_context_layer)
314 return; 268 return;
315 [ca_context_layer removeFromSuperlayer]; 269 [ca_context_layer removeFromSuperlayer];
316 if (ca_context_layer == ca_context_layer_) 270 if (ca_context_layer == ca_context_layer_)
317 ca_context_layer_.reset(); 271 ca_context_layer_.reset();
318 } 272 }
319 273
320 void AcceleratedWidgetMac::DestroyIOSurfaceLayer( 274 void AcceleratedWidgetMac::DestroyLocalLayer() {
321 base::scoped_nsobject<IOSurfaceLayer> io_surface_layer) { 275 if (!local_layer_)
322 if (!io_surface_layer)
323 return; 276 return;
324 [io_surface_layer resetClient]; 277 [local_layer_ removeFromSuperlayer];
325 [io_surface_layer removeFromSuperlayer]; 278 local_layer_.reset();
326 if (io_surface_layer == io_surface_layer_)
327 io_surface_layer_.reset();
328 }
329
330 void AcceleratedWidgetMac::DestroySoftwareLayer() {
331 if (!software_layer_)
332 return;
333 [software_layer_ removeFromSuperlayer];
334 software_layer_.reset();
335 }
336
337 bool AcceleratedWidgetMac::IOSurfaceLayerShouldAckImmediately() const {
338 // If there is no view then the accelerated layer is not in the view
339 // hierarchy and will never draw.
340 if (!view_)
341 return true;
342 return view_->AcceleratedWidgetShouldIgnoreBackpressure();
343 }
344
345 void AcceleratedWidgetMac::IOSurfaceLayerDidDrawFrame() {
346 AcknowledgeAcceleratedFrame();
347 } 279 }
348 280
349 void AcceleratedWidgetMac::AcknowledgeAcceleratedFrame() { 281 void AcceleratedWidgetMac::AcknowledgeAcceleratedFrame() {
350 if (accelerated_frame_drawn_callback_.is_null()) 282 if (accelerated_frame_drawn_callback_.is_null())
351 return; 283 return;
352 accelerated_frame_drawn_callback_.Run(); 284 accelerated_frame_drawn_callback_.Run();
353 accelerated_frame_drawn_callback_.Reset(); 285 accelerated_frame_drawn_callback_.Reset();
354 if (view_) 286 if (view_)
355 view_->AcceleratedWidgetSwapCompleted(accelerated_latency_info_); 287 view_->AcceleratedWidgetSwapCompleted(accelerated_latency_info_);
356 accelerated_latency_info_.clear(); 288 accelerated_latency_info_.clear();
357 } 289 }
358 290
359 void AcceleratedWidgetMac::IOSurfaceLayerHitError() {
360 // Perform all acks that would have been done if the frame had succeeded, to
361 // un-block the compositor and renderer.
362 AcknowledgeAcceleratedFrame();
363
364 // Poison the context being used and request a mulligan.
365 [io_surface_layer_ poisonContextAndSharegroup];
366
367 if (view_)
368 view_->AcceleratedWidgetHitError();
369 }
370
371 void AcceleratedWidgetMacGotAcceleratedFrame( 291 void AcceleratedWidgetMacGotAcceleratedFrame(
372 gfx::AcceleratedWidget widget, uint64 surface_handle, 292 gfx::AcceleratedWidget widget, uint64 surface_handle,
373 const std::vector<ui::LatencyInfo>& latency_info, 293 const std::vector<ui::LatencyInfo>& latency_info,
374 const gfx::Size& pixel_size, 294 const gfx::Size& pixel_size,
375 float scale_factor, 295 float scale_factor,
376 const gfx::Rect& pixel_damage_rect, 296 const gfx::Rect& pixel_damage_rect,
377 const base::Closure& drawn_callback, 297 const base::Closure& drawn_callback,
378 bool* disable_throttling, int* renderer_id, 298 bool* disable_throttling, int* renderer_id,
379 base::TimeTicks* vsync_timebase, base::TimeDelta* vsync_interval) { 299 base::TimeTicks* vsync_timebase, base::TimeDelta* vsync_interval) {
380 AcceleratedWidgetMac* accelerated_widget_mac = 300 AcceleratedWidgetMac* accelerated_widget_mac =
381 GetHelperFromAcceleratedWidget(widget); 301 GetHelperFromAcceleratedWidget(widget);
382 if (accelerated_widget_mac) { 302 if (accelerated_widget_mac) {
383 accelerated_widget_mac->GotAcceleratedFrame( 303 accelerated_widget_mac->GotAcceleratedFrame(
384 surface_handle, latency_info, pixel_size, scale_factor, 304 surface_handle, latency_info, pixel_size, scale_factor,
385 pixel_damage_rect, drawn_callback); 305 pixel_damage_rect, drawn_callback);
386 *disable_throttling = 306 *disable_throttling =
387 accelerated_widget_mac->IsRendererThrottlingDisabled(); 307 accelerated_widget_mac->IsRendererThrottlingDisabled();
388 *renderer_id = accelerated_widget_mac->GetRendererID(); 308 *renderer_id = accelerated_widget_mac->GetRendererID();
389 accelerated_widget_mac->GetVSyncParameters(vsync_timebase, vsync_interval); 309 accelerated_widget_mac->GetVSyncParameters(vsync_timebase, vsync_interval);
390 } else { 310 } else {
391 *disable_throttling = false; 311 *disable_throttling = false;
392 *renderer_id = 0; 312 *renderer_id = 0;
393 *vsync_timebase = base::TimeTicks(); 313 *vsync_timebase = base::TimeTicks();
394 *vsync_interval = base::TimeDelta(); 314 *vsync_interval = base::TimeDelta();
395 } 315 }
396 } 316 }
397 317
398 void AcceleratedWidgetMacGotSoftwareFrame( 318 void AcceleratedWidgetMacGotIOSurfaceFrame(
399 gfx::AcceleratedWidget widget, float scale_factor, SkCanvas* canvas) { 319 gfx::AcceleratedWidget widget,
320 base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
321 const gfx::Size& pixel_size,
322 float scale_factor,
323 bool flip_y) {
400 AcceleratedWidgetMac* accelerated_widget_mac = 324 AcceleratedWidgetMac* accelerated_widget_mac =
401 GetHelperFromAcceleratedWidget(widget); 325 GetHelperFromAcceleratedWidget(widget);
402 if (accelerated_widget_mac) 326 if (accelerated_widget_mac) {
403 accelerated_widget_mac->GotSoftwareFrame(scale_factor, canvas); 327 accelerated_widget_mac->GotIOSurfaceFrame(io_surface, pixel_size,
328 scale_factor, flip_y);
329 }
404 } 330 }
405 331
406 } // namespace ui 332 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698