OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/ca_renderer_layer_tree.h" | 5 #include "ui/accelerated_widget_mac/ca_renderer_layer_tree.h" |
6 | 6 |
7 #include <AVFoundation/AVFoundation.h> | 7 #include <AVFoundation/AVFoundation.h> |
8 #include <CoreMedia/CoreMedia.h> | 8 #include <CoreMedia/CoreMedia.h> |
9 #include <CoreVideo/CoreVideo.h> | 9 #include <CoreVideo/CoreVideo.h> |
10 #include <GLES2/gl2extchromium.h> | 10 #include <GLES2/gl2extchromium.h> |
11 | 11 |
12 #include "base/command_line.h" | 12 #include "base/command_line.h" |
13 #include "base/lazy_instance.h" | |
13 #include "base/mac/sdk_forward_declarations.h" | 14 #include "base/mac/sdk_forward_declarations.h" |
14 #include "base/trace_event/trace_event.h" | 15 #include "base/trace_event/trace_event.h" |
15 #include "third_party/skia/include/core/SkColor.h" | 16 #include "third_party/skia/include/core/SkColor.h" |
16 #include "ui/base/cocoa/animation_utils.h" | 17 #include "ui/base/cocoa/animation_utils.h" |
17 #include "ui/base/ui_base_switches.h" | 18 #include "ui/base/ui_base_switches.h" |
18 #include "ui/gfx/geometry/dip_util.h" | 19 #include "ui/gfx/geometry/dip_util.h" |
19 #include "ui/gl/ca_renderer_layer_params.h" | 20 #include "ui/gl/ca_renderer_layer_params.h" |
20 #include "ui/gl/gl_image_io_surface.h" | 21 #include "ui/gl/gl_image_io_surface.h" |
21 | 22 |
22 #if !defined(MAC_OS_X_VERSION_10_8) || \ | 23 #if !defined(MAC_OS_X_VERSION_10_8) || \ |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
122 LOG(ERROR) << "CVPixelBufferCreateWithIOSurface failed with " << cv_return; | 123 LOG(ERROR) << "CVPixelBufferCreateWithIOSurface failed with " << cv_return; |
123 return false; | 124 return false; |
124 } | 125 } |
125 | 126 |
126 return AVSampleBufferDisplayLayerEnqueueCVPixelBuffer(av_layer, | 127 return AVSampleBufferDisplayLayerEnqueueCVPixelBuffer(av_layer, |
127 cv_pixel_buffer); | 128 cv_pixel_buffer); |
128 } | 129 } |
129 | 130 |
130 } // namespace | 131 } // namespace |
131 | 132 |
133 class CARendererLayerTree::SolidColorContents | |
134 : public base::RefCounted<CARendererLayerTree::SolidColorContents> { | |
135 public: | |
136 static scoped_refptr<SolidColorContents> Get(SkColor color); | |
137 id GetContents() const; | |
138 | |
139 private: | |
140 friend class base::RefCounted<SolidColorContents>; | |
141 | |
142 SolidColorContents(SkColor color, IOSurfaceRef io_surface); | |
143 ~SolidColorContents(); | |
144 | |
145 SkColor color_ = 0; | |
146 base::ScopedCFTypeRef<IOSurfaceRef> io_surface_; | |
147 static base::LazyInstance<std::map<SkColor, SolidColorContents*>> map_; | |
148 }; | |
149 | |
150 base::LazyInstance<std::map<SkColor, CARendererLayerTree::SolidColorContents*>> | |
151 CARendererLayerTree::SolidColorContents::map_; | |
152 | |
153 // static | |
154 scoped_refptr<CARendererLayerTree::SolidColorContents> | |
155 CARendererLayerTree::SolidColorContents::Get(SkColor color) { | |
156 const int kSolidColorContentsSize = 16; | |
157 | |
158 auto found = map_.Get().find(color); | |
159 if (found != map_.Get().end()) | |
160 return found->second; | |
161 | |
162 IOSurfaceRef io_surface = CreateIOSurface( | |
163 gfx::Size(kSolidColorContentsSize, kSolidColorContentsSize), | |
164 gfx::BufferFormat::BGRA_8888); | |
165 if (!io_surface) | |
166 return nullptr; | |
167 | |
168 size_t bytes_per_row = IOSurfaceGetBytesPerRowOfPlane(io_surface, 0); | |
169 IOSurfaceLock(io_surface, 0, NULL); | |
erikchen
2016/09/29 18:23:26
s/NULL/nullptr
| |
170 char* row_base_address = | |
171 reinterpret_cast<char*>(IOSurfaceGetBaseAddress(io_surface)); | |
172 for (int i = 0; i < kSolidColorContentsSize; ++i) { | |
173 unsigned int* pixel = reinterpret_cast<unsigned int*>(row_base_address); | |
174 for (int j = 0; j < kSolidColorContentsSize; ++j) | |
175 *(pixel++) = color; | |
176 row_base_address += bytes_per_row; | |
177 } | |
178 IOSurfaceUnlock(io_surface, 0, NULL); | |
179 | |
180 return new SolidColorContents(color, io_surface); | |
181 } | |
182 | |
183 id CARendererLayerTree::SolidColorContents::GetContents() const { | |
184 return static_cast<id>(io_surface_.get()); | |
185 } | |
186 | |
187 CARendererLayerTree::SolidColorContents::SolidColorContents( | |
188 SkColor color, | |
189 IOSurfaceRef io_surface) | |
190 : color_(color), io_surface_(io_surface) { | |
191 DCHECK(map_.Get().find(color_) == map_.Get().end()); | |
192 map_.Get()[color_] = this; | |
193 } | |
194 | |
195 CARendererLayerTree::SolidColorContents::~SolidColorContents() { | |
196 auto found = map_.Get().find(color_); | |
197 DCHECK(found != map_.Get().end()); | |
198 DCHECK(found->second == this); | |
199 map_.Get().erase(color_); | |
200 } | |
201 | |
132 CARendererLayerTree::CARendererLayerTree( | 202 CARendererLayerTree::CARendererLayerTree( |
133 bool allow_av_sample_buffer_display_layer) | 203 bool allow_av_sample_buffer_display_layer) |
134 : allow_av_sample_buffer_display_layer_( | 204 : allow_av_sample_buffer_display_layer_( |
135 allow_av_sample_buffer_display_layer) {} | 205 allow_av_sample_buffer_display_layer) {} |
136 CARendererLayerTree::~CARendererLayerTree() {} | 206 CARendererLayerTree::~CARendererLayerTree() {} |
137 | 207 |
138 bool CARendererLayerTree::ScheduleCALayer(const CARendererLayerParams& params) { | 208 bool CARendererLayerTree::ScheduleCALayer(const CARendererLayerParams& params) { |
139 // Excessive logging to debug white screens (crbug.com/583805). | 209 // Excessive logging to debug white screens (crbug.com/583805). |
140 // TODO(ccameron): change this back to a DLOG. | 210 // TODO(ccameron): change this back to a DLOG. |
141 if (has_committed_) { | 211 if (has_committed_) { |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
282 : io_surface(io_surface), | 352 : io_surface(io_surface), |
283 cv_pixel_buffer(cv_pixel_buffer), | 353 cv_pixel_buffer(cv_pixel_buffer), |
284 contents_rect(contents_rect), | 354 contents_rect(contents_rect), |
285 rect(rect), | 355 rect(rect), |
286 background_color(background_color), | 356 background_color(background_color), |
287 ca_edge_aa_mask(0), | 357 ca_edge_aa_mask(0), |
288 opacity(opacity), | 358 opacity(opacity), |
289 ca_filter(filter == GL_LINEAR ? kCAFilterLinear : kCAFilterNearest) { | 359 ca_filter(filter == GL_LINEAR ? kCAFilterLinear : kCAFilterNearest) { |
290 DCHECK(filter == GL_LINEAR || filter == GL_NEAREST); | 360 DCHECK(filter == GL_LINEAR || filter == GL_NEAREST); |
291 | 361 |
362 // On Mac OS Sierra, solid color layers are not color color corrected to the | |
363 // output monitor color space, but IOSurface-backed layers are color | |
364 // corrected. Note that this is only the case when the CALayers are shared | |
365 // across processes. To make colors consistent across both solid color and | |
366 // IOSurface-backed layers, use a cache of solid-color IOSurfaces as contents. | |
367 // https://crbug.com/633805 | |
368 if (base::mac::IsAtLeastOS10_12()) { | |
erikchen
2016/09/29 18:23:26
IWYU
| |
369 solid_color_contents = SolidColorContents::Get(background_color); | |
370 ContentLayer::contents_rect = gfx::RectF(0, 0, 1, 1); | |
371 } | |
372 | |
292 // Because the root layer has setGeometryFlipped:YES, there is some ambiguity | 373 // Because the root layer has setGeometryFlipped:YES, there is some ambiguity |
293 // about what exactly top and bottom mean. This ambiguity is resolved in | 374 // about what exactly top and bottom mean. This ambiguity is resolved in |
294 // different ways for solid color CALayers and for CALayers that have content | 375 // different ways for solid color CALayers and for CALayers that have content |
295 // (surprise!). For CALayers with IOSurface content, the top edge in the AA | 376 // (surprise!). For CALayers with IOSurface content, the top edge in the AA |
296 // mask refers to what appears as the bottom edge on-screen. For CALayers | 377 // mask refers to what appears as the bottom edge on-screen. For CALayers |
297 // without content (solid color layers), the top edge in the AA mask is the | 378 // without content (solid color layers), the top edge in the AA mask is the |
298 // top edge on-screen. | 379 // top edge on-screen. |
299 // https://crbug.com/567946 | 380 // https://crbug.com/567946 |
300 if (edge_aa_mask & GL_CA_LAYER_EDGE_LEFT_CHROMIUM) | 381 if (edge_aa_mask & GL_CA_LAYER_EDGE_LEFT_CHROMIUM) |
301 ca_edge_aa_mask |= kCALayerLeftEdge; | 382 ca_edge_aa_mask |= kCALayerLeftEdge; |
302 if (edge_aa_mask & GL_CA_LAYER_EDGE_RIGHT_CHROMIUM) | 383 if (edge_aa_mask & GL_CA_LAYER_EDGE_RIGHT_CHROMIUM) |
303 ca_edge_aa_mask |= kCALayerRightEdge; | 384 ca_edge_aa_mask |= kCALayerRightEdge; |
304 if (io_surface) { | 385 if (io_surface || solid_color_contents) { |
305 if (edge_aa_mask & GL_CA_LAYER_EDGE_TOP_CHROMIUM) | 386 if (edge_aa_mask & GL_CA_LAYER_EDGE_TOP_CHROMIUM) |
306 ca_edge_aa_mask |= kCALayerBottomEdge; | 387 ca_edge_aa_mask |= kCALayerBottomEdge; |
307 if (edge_aa_mask & GL_CA_LAYER_EDGE_BOTTOM_CHROMIUM) | 388 if (edge_aa_mask & GL_CA_LAYER_EDGE_BOTTOM_CHROMIUM) |
308 ca_edge_aa_mask |= kCALayerTopEdge; | 389 ca_edge_aa_mask |= kCALayerTopEdge; |
309 } else { | 390 } else { |
310 if (edge_aa_mask & GL_CA_LAYER_EDGE_TOP_CHROMIUM) | 391 if (edge_aa_mask & GL_CA_LAYER_EDGE_TOP_CHROMIUM) |
311 ca_edge_aa_mask |= kCALayerTopEdge; | 392 ca_edge_aa_mask |= kCALayerTopEdge; |
312 if (edge_aa_mask & GL_CA_LAYER_EDGE_BOTTOM_CHROMIUM) | 393 if (edge_aa_mask & GL_CA_LAYER_EDGE_BOTTOM_CHROMIUM) |
313 ca_edge_aa_mask |= kCALayerBottomEdge; | 394 ca_edge_aa_mask |= kCALayerBottomEdge; |
314 } | 395 } |
315 | 396 |
316 // Only allow 4:2:0 frames which fill the layer's contents to be promoted to | 397 // Only allow 4:2:0 frames which fill the layer's contents to be promoted to |
317 // AV layers. | 398 // AV layers. |
318 if (tree->allow_av_sample_buffer_display_layer_ && | 399 if (tree->allow_av_sample_buffer_display_layer_ && |
319 IOSurfaceGetPixelFormat(io_surface) == | 400 IOSurfaceGetPixelFormat(io_surface) == |
320 kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange && | 401 kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange && |
321 contents_rect == gfx::RectF(0, 0, 1, 1)) { | 402 contents_rect == gfx::RectF(0, 0, 1, 1)) { |
322 use_av_layer = true; | 403 use_av_layer = true; |
323 } | 404 } |
324 } | 405 } |
325 | 406 |
326 CARendererLayerTree::ContentLayer::ContentLayer(ContentLayer&& layer) | 407 CARendererLayerTree::ContentLayer::ContentLayer(ContentLayer&& layer) |
327 : io_surface(layer.io_surface), | 408 : io_surface(layer.io_surface), |
328 cv_pixel_buffer(layer.cv_pixel_buffer), | 409 cv_pixel_buffer(layer.cv_pixel_buffer), |
410 solid_color_contents(layer.solid_color_contents), | |
329 contents_rect(layer.contents_rect), | 411 contents_rect(layer.contents_rect), |
330 rect(layer.rect), | 412 rect(layer.rect), |
331 background_color(layer.background_color), | 413 background_color(layer.background_color), |
332 ca_edge_aa_mask(layer.ca_edge_aa_mask), | 414 ca_edge_aa_mask(layer.ca_edge_aa_mask), |
333 opacity(layer.opacity), | 415 opacity(layer.opacity), |
334 ca_filter(layer.ca_filter), | 416 ca_filter(layer.ca_filter), |
335 ca_layer(std::move(layer.ca_layer)), | 417 ca_layer(std::move(layer.ca_layer)), |
336 av_layer(std::move(layer.av_layer)), | 418 av_layer(std::move(layer.av_layer)), |
337 use_av_layer(layer.use_av_layer) { | 419 use_av_layer(layer.use_av_layer) { |
338 DCHECK(!layer.ca_layer); | 420 DCHECK(!layer.ca_layer); |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
541 bool update_rect = true; | 623 bool update_rect = true; |
542 bool update_background_color = true; | 624 bool update_background_color = true; |
543 bool update_ca_edge_aa_mask = true; | 625 bool update_ca_edge_aa_mask = true; |
544 bool update_opacity = true; | 626 bool update_opacity = true; |
545 bool update_ca_filter = true; | 627 bool update_ca_filter = true; |
546 if (old_layer && old_layer->use_av_layer == use_av_layer) { | 628 if (old_layer && old_layer->use_av_layer == use_av_layer) { |
547 DCHECK(old_layer->ca_layer); | 629 DCHECK(old_layer->ca_layer); |
548 std::swap(ca_layer, old_layer->ca_layer); | 630 std::swap(ca_layer, old_layer->ca_layer); |
549 std::swap(av_layer, old_layer->av_layer); | 631 std::swap(av_layer, old_layer->av_layer); |
550 update_contents = old_layer->io_surface != io_surface || | 632 update_contents = old_layer->io_surface != io_surface || |
551 old_layer->cv_pixel_buffer != cv_pixel_buffer; | 633 old_layer->cv_pixel_buffer != cv_pixel_buffer || |
634 old_layer->solid_color_contents != solid_color_contents; | |
552 update_contents_rect = old_layer->contents_rect != contents_rect; | 635 update_contents_rect = old_layer->contents_rect != contents_rect; |
553 update_rect = old_layer->rect != rect; | 636 update_rect = old_layer->rect != rect; |
554 update_background_color = old_layer->background_color != background_color; | 637 update_background_color = old_layer->background_color != background_color; |
555 update_ca_edge_aa_mask = old_layer->ca_edge_aa_mask != ca_edge_aa_mask; | 638 update_ca_edge_aa_mask = old_layer->ca_edge_aa_mask != ca_edge_aa_mask; |
556 update_opacity = old_layer->opacity != opacity; | 639 update_opacity = old_layer->opacity != opacity; |
557 update_ca_filter = old_layer->ca_filter != ca_filter; | 640 update_ca_filter = old_layer->ca_filter != ca_filter; |
558 } else { | 641 } else { |
559 if (use_av_layer) { | 642 if (use_av_layer) { |
560 av_layer.reset([[AVSampleBufferDisplayLayer alloc] init]); | 643 av_layer.reset([[AVSampleBufferDisplayLayer alloc] init]); |
561 ca_layer.reset([av_layer retain]); | 644 ca_layer.reset([av_layer retain]); |
(...skipping 16 matching lines...) Expand all Loading... | |
578 if (update_contents) { | 661 if (update_contents) { |
579 if (cv_pixel_buffer) { | 662 if (cv_pixel_buffer) { |
580 AVSampleBufferDisplayLayerEnqueueCVPixelBuffer(av_layer, | 663 AVSampleBufferDisplayLayerEnqueueCVPixelBuffer(av_layer, |
581 cv_pixel_buffer); | 664 cv_pixel_buffer); |
582 } else { | 665 } else { |
583 AVSampleBufferDisplayLayerEnqueueIOSurface(av_layer, io_surface); | 666 AVSampleBufferDisplayLayerEnqueueIOSurface(av_layer, io_surface); |
584 } | 667 } |
585 } | 668 } |
586 } else { | 669 } else { |
587 if (update_contents) { | 670 if (update_contents) { |
588 [ca_layer setContents:static_cast<id>(io_surface.get())]; | 671 if (io_surface) { |
672 [ca_layer setContents:static_cast<id>(io_surface.get())]; | |
673 } else if (solid_color_contents) { | |
674 [ca_layer setContents:solid_color_contents->GetContents()]; | |
675 } | |
589 if ([ca_layer respondsToSelector:(@selector(setContentsScale:))]) | 676 if ([ca_layer respondsToSelector:(@selector(setContentsScale:))]) |
590 [ca_layer setContentsScale:scale_factor]; | 677 [ca_layer setContentsScale:scale_factor]; |
591 } | 678 } |
592 if (update_contents_rect) | 679 if (update_contents_rect) |
593 [ca_layer setContentsRect:contents_rect.ToCGRect()]; | 680 [ca_layer setContentsRect:contents_rect.ToCGRect()]; |
594 } | 681 } |
595 if (update_rect) { | 682 if (update_rect) { |
596 gfx::RectF dip_rect = gfx::RectF(rect); | 683 gfx::RectF dip_rect = gfx::RectF(rect); |
597 dip_rect.Scale(1 / scale_factor); | 684 dip_rect.Scale(1 / scale_factor); |
598 [ca_layer setPosition:CGPointMake(dip_rect.x(), dip_rect.y())]; | 685 [ca_layer setPosition:CGPointMake(dip_rect.x(), dip_rect.y())]; |
(...skipping 20 matching lines...) Expand all Loading... | |
619 } | 706 } |
620 | 707 |
621 static bool show_borders = base::CommandLine::ForCurrentProcess()->HasSwitch( | 708 static bool show_borders = base::CommandLine::ForCurrentProcess()->HasSwitch( |
622 switches::kShowMacOverlayBorders); | 709 switches::kShowMacOverlayBorders); |
623 if (show_borders) { | 710 if (show_borders) { |
624 base::ScopedCFTypeRef<CGColorRef> color; | 711 base::ScopedCFTypeRef<CGColorRef> color; |
625 if (update_anything) { | 712 if (update_anything) { |
626 if (use_av_layer) { | 713 if (use_av_layer) { |
627 // Yellow represents an AV layer that changed this frame. | 714 // Yellow represents an AV layer that changed this frame. |
628 color.reset(CGColorCreateGenericRGB(1, 1, 0, 1)); | 715 color.reset(CGColorCreateGenericRGB(1, 1, 0, 1)); |
629 } else { | 716 } else if (io_surface) { |
630 // Pink represents a CALayer that changed this frame. | 717 // Pink represents a CALayer that changed this frame. |
631 color.reset(CGColorCreateGenericRGB(1, 0, 1, 1)); | 718 color.reset(CGColorCreateGenericRGB(1, 0, 1, 1)); |
719 } else if (solid_color_contents) { | |
720 // Cyan represents a solid color IOSurface-backed layer. | |
721 color.reset(CGColorCreateGenericRGB(0, 1, 1, 1)); | |
722 } else { | |
723 // Red represents a solid color layer. | |
724 color.reset(CGColorCreateGenericRGB(1, 0, 0, 1)); | |
632 } | 725 } |
633 } else { | 726 } else { |
634 // Grey represents a CALayer that has not changed. | 727 // Grey represents a CALayer that has not changed. |
635 color.reset(CGColorCreateGenericRGB(0.5, 0.5, 0.5, 1)); | 728 color.reset(CGColorCreateGenericRGB(0.5, 0.5, 0.5, 1)); |
636 } | 729 } |
637 [ca_layer setBorderWidth:1]; | 730 [ca_layer setBorderWidth:1]; |
638 [ca_layer setBorderColor:color]; | 731 [ca_layer setBorderColor:color]; |
639 } | 732 } |
640 } | 733 } |
641 | 734 |
642 } // namespace ui | 735 } // namespace ui |
OLD | NEW |