Chromium Code Reviews| 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 |