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

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

Issue 2391793002: Mac: Fix bugs in Sierra color fix (Closed)
Patch Set: Created 4 years, 2 months 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
« no previous file with comments | « ui/accelerated_widget_mac/ca_renderer_layer_tree.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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);
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,
204 bool allow_solid_color_layers)
134 : allow_av_sample_buffer_display_layer_( 205 : allow_av_sample_buffer_display_layer_(
135 allow_av_sample_buffer_display_layer) {} 206 allow_av_sample_buffer_display_layer),
207 allow_solid_color_layers_(allow_solid_color_layers) {}
136 CARendererLayerTree::~CARendererLayerTree() {} 208 CARendererLayerTree::~CARendererLayerTree() {}
137 209
138 bool CARendererLayerTree::ScheduleCALayer(const CARendererLayerParams& params) { 210 bool CARendererLayerTree::ScheduleCALayer(const CARendererLayerParams& params) {
139 // Excessive logging to debug white screens (crbug.com/583805). 211 // Excessive logging to debug white screens (crbug.com/583805).
140 // TODO(ccameron): change this back to a DLOG. 212 // TODO(ccameron): change this back to a DLOG.
141 if (has_committed_) { 213 if (has_committed_) {
142 LOG(ERROR) << "ScheduleCALayer called after CommitScheduledCALayers."; 214 LOG(ERROR) << "ScheduleCALayer called after CommitScheduledCALayers.";
143 return false; 215 return false;
144 } 216 }
145 return root_layer_.AddContentLayer(this, params); 217 return root_layer_.AddContentLayer(this, params);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 fullscreen_low_power_layer, video_layer->cv_pixel_buffer); 281 fullscreen_low_power_layer, video_layer->cv_pixel_buffer);
210 } else { 282 } else {
211 AVSampleBufferDisplayLayerEnqueueIOSurface(fullscreen_low_power_layer, 283 AVSampleBufferDisplayLayerEnqueueIOSurface(fullscreen_low_power_layer,
212 video_layer->io_surface); 284 video_layer->io_surface);
213 } 285 }
214 [fullscreen_low_power_layer setVideoGravity:AVLayerVideoGravityResize]; 286 [fullscreen_low_power_layer setVideoGravity:AVLayerVideoGravityResize];
215 [fullscreen_low_power_layer setFrame:video_layer_frame_dip.ToCGRect()]; 287 [fullscreen_low_power_layer setFrame:video_layer_frame_dip.ToCGRect()];
216 return true; 288 return true;
217 } 289 }
218 290
291 id CARendererLayerTree::ContentsForSolidColorForTesting(SkColor color) {
292 return SolidColorContents::Get(color)->GetContents();
293 }
219 294
220 CARendererLayerTree::RootLayer::RootLayer() {} 295 CARendererLayerTree::RootLayer::RootLayer() {}
221 296
222 // Note that for all destructors, the the CALayer will have been reset to nil if 297 // Note that for all destructors, the the CALayer will have been reset to nil if
223 // another layer has taken it. 298 // another layer has taken it.
224 CARendererLayerTree::RootLayer::~RootLayer() { 299 CARendererLayerTree::RootLayer::~RootLayer() {
225 [ca_layer removeFromSuperlayer]; 300 [ca_layer removeFromSuperlayer];
226 } 301 }
227 302
228 CARendererLayerTree::ClipAndSortingLayer::ClipAndSortingLayer( 303 CARendererLayerTree::ClipAndSortingLayer::ClipAndSortingLayer(
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
282 : io_surface(io_surface), 357 : io_surface(io_surface),
283 cv_pixel_buffer(cv_pixel_buffer), 358 cv_pixel_buffer(cv_pixel_buffer),
284 contents_rect(contents_rect), 359 contents_rect(contents_rect),
285 rect(rect), 360 rect(rect),
286 background_color(background_color), 361 background_color(background_color),
287 ca_edge_aa_mask(0), 362 ca_edge_aa_mask(0),
288 opacity(opacity), 363 opacity(opacity),
289 ca_filter(filter == GL_LINEAR ? kCAFilterLinear : kCAFilterNearest) { 364 ca_filter(filter == GL_LINEAR ? kCAFilterLinear : kCAFilterNearest) {
290 DCHECK(filter == GL_LINEAR || filter == GL_NEAREST); 365 DCHECK(filter == GL_LINEAR || filter == GL_NEAREST);
291 366
367 // On Mac OS Sierra, solid color layers are not color color corrected to the
368 // output monitor color space, but IOSurface-backed layers are color
369 // corrected. Note that this is only the case when the CALayers are shared
370 // across processes. To make colors consistent across both solid color and
371 // IOSurface-backed layers, use a cache of solid-color IOSurfaces as contents.
372 // https://crbug.com/633805
373 if (!io_surface && !tree->allow_solid_color_layers_) {
374 solid_color_contents = SolidColorContents::Get(background_color);
375 ContentLayer::contents_rect = gfx::RectF(0, 0, 1, 1);
376 }
377
292 // Because the root layer has setGeometryFlipped:YES, there is some ambiguity 378 // Because the root layer has setGeometryFlipped:YES, there is some ambiguity
293 // about what exactly top and bottom mean. This ambiguity is resolved in 379 // 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 380 // 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 381 // (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 382 // 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 383 // without content (solid color layers), the top edge in the AA mask is the
298 // top edge on-screen. 384 // top edge on-screen.
299 // https://crbug.com/567946 385 // https://crbug.com/567946
300 if (edge_aa_mask & GL_CA_LAYER_EDGE_LEFT_CHROMIUM) 386 if (edge_aa_mask & GL_CA_LAYER_EDGE_LEFT_CHROMIUM)
301 ca_edge_aa_mask |= kCALayerLeftEdge; 387 ca_edge_aa_mask |= kCALayerLeftEdge;
302 if (edge_aa_mask & GL_CA_LAYER_EDGE_RIGHT_CHROMIUM) 388 if (edge_aa_mask & GL_CA_LAYER_EDGE_RIGHT_CHROMIUM)
303 ca_edge_aa_mask |= kCALayerRightEdge; 389 ca_edge_aa_mask |= kCALayerRightEdge;
304 if (io_surface) { 390 if (io_surface || solid_color_contents) {
305 if (edge_aa_mask & GL_CA_LAYER_EDGE_TOP_CHROMIUM) 391 if (edge_aa_mask & GL_CA_LAYER_EDGE_TOP_CHROMIUM)
306 ca_edge_aa_mask |= kCALayerBottomEdge; 392 ca_edge_aa_mask |= kCALayerBottomEdge;
307 if (edge_aa_mask & GL_CA_LAYER_EDGE_BOTTOM_CHROMIUM) 393 if (edge_aa_mask & GL_CA_LAYER_EDGE_BOTTOM_CHROMIUM)
308 ca_edge_aa_mask |= kCALayerTopEdge; 394 ca_edge_aa_mask |= kCALayerTopEdge;
309 } else { 395 } else {
310 if (edge_aa_mask & GL_CA_LAYER_EDGE_TOP_CHROMIUM) 396 if (edge_aa_mask & GL_CA_LAYER_EDGE_TOP_CHROMIUM)
311 ca_edge_aa_mask |= kCALayerTopEdge; 397 ca_edge_aa_mask |= kCALayerTopEdge;
312 if (edge_aa_mask & GL_CA_LAYER_EDGE_BOTTOM_CHROMIUM) 398 if (edge_aa_mask & GL_CA_LAYER_EDGE_BOTTOM_CHROMIUM)
313 ca_edge_aa_mask |= kCALayerBottomEdge; 399 ca_edge_aa_mask |= kCALayerBottomEdge;
314 } 400 }
315 401
316 // Only allow 4:2:0 frames which fill the layer's contents to be promoted to 402 // Only allow 4:2:0 frames which fill the layer's contents to be promoted to
317 // AV layers. 403 // AV layers.
318 if (tree->allow_av_sample_buffer_display_layer_ && 404 if (tree->allow_av_sample_buffer_display_layer_ &&
319 IOSurfaceGetPixelFormat(io_surface) == 405 IOSurfaceGetPixelFormat(io_surface) ==
320 kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange && 406 kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange &&
321 contents_rect == gfx::RectF(0, 0, 1, 1)) { 407 contents_rect == gfx::RectF(0, 0, 1, 1)) {
322 use_av_layer = true; 408 use_av_layer = true;
323 } 409 }
324 } 410 }
325 411
326 CARendererLayerTree::ContentLayer::ContentLayer(ContentLayer&& layer) 412 CARendererLayerTree::ContentLayer::ContentLayer(ContentLayer&& layer)
327 : io_surface(layer.io_surface), 413 : io_surface(layer.io_surface),
328 cv_pixel_buffer(layer.cv_pixel_buffer), 414 cv_pixel_buffer(layer.cv_pixel_buffer),
415 solid_color_contents(layer.solid_color_contents),
329 contents_rect(layer.contents_rect), 416 contents_rect(layer.contents_rect),
330 rect(layer.rect), 417 rect(layer.rect),
331 background_color(layer.background_color), 418 background_color(layer.background_color),
332 ca_edge_aa_mask(layer.ca_edge_aa_mask), 419 ca_edge_aa_mask(layer.ca_edge_aa_mask),
333 opacity(layer.opacity), 420 opacity(layer.opacity),
334 ca_filter(layer.ca_filter), 421 ca_filter(layer.ca_filter),
335 ca_layer(std::move(layer.ca_layer)), 422 ca_layer(std::move(layer.ca_layer)),
336 av_layer(std::move(layer.av_layer)), 423 av_layer(std::move(layer.av_layer)),
337 use_av_layer(layer.use_av_layer) { 424 use_av_layer(layer.use_av_layer) {
338 DCHECK(!layer.ca_layer); 425 DCHECK(!layer.ca_layer);
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
541 bool update_rect = true; 628 bool update_rect = true;
542 bool update_background_color = true; 629 bool update_background_color = true;
543 bool update_ca_edge_aa_mask = true; 630 bool update_ca_edge_aa_mask = true;
544 bool update_opacity = true; 631 bool update_opacity = true;
545 bool update_ca_filter = true; 632 bool update_ca_filter = true;
546 if (old_layer && old_layer->use_av_layer == use_av_layer) { 633 if (old_layer && old_layer->use_av_layer == use_av_layer) {
547 DCHECK(old_layer->ca_layer); 634 DCHECK(old_layer->ca_layer);
548 std::swap(ca_layer, old_layer->ca_layer); 635 std::swap(ca_layer, old_layer->ca_layer);
549 std::swap(av_layer, old_layer->av_layer); 636 std::swap(av_layer, old_layer->av_layer);
550 update_contents = old_layer->io_surface != io_surface || 637 update_contents = old_layer->io_surface != io_surface ||
551 old_layer->cv_pixel_buffer != cv_pixel_buffer; 638 old_layer->cv_pixel_buffer != cv_pixel_buffer ||
639 old_layer->solid_color_contents != solid_color_contents;
552 update_contents_rect = old_layer->contents_rect != contents_rect; 640 update_contents_rect = old_layer->contents_rect != contents_rect;
553 update_rect = old_layer->rect != rect; 641 update_rect = old_layer->rect != rect;
554 update_background_color = old_layer->background_color != background_color; 642 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; 643 update_ca_edge_aa_mask = old_layer->ca_edge_aa_mask != ca_edge_aa_mask;
556 update_opacity = old_layer->opacity != opacity; 644 update_opacity = old_layer->opacity != opacity;
557 update_ca_filter = old_layer->ca_filter != ca_filter; 645 update_ca_filter = old_layer->ca_filter != ca_filter;
558 } else { 646 } else {
559 if (use_av_layer) { 647 if (use_av_layer) {
560 av_layer.reset([[AVSampleBufferDisplayLayer alloc] init]); 648 av_layer.reset([[AVSampleBufferDisplayLayer alloc] init]);
561 ca_layer.reset([av_layer retain]); 649 ca_layer.reset([av_layer retain]);
(...skipping 16 matching lines...) Expand all
578 if (update_contents) { 666 if (update_contents) {
579 if (cv_pixel_buffer) { 667 if (cv_pixel_buffer) {
580 AVSampleBufferDisplayLayerEnqueueCVPixelBuffer(av_layer, 668 AVSampleBufferDisplayLayerEnqueueCVPixelBuffer(av_layer,
581 cv_pixel_buffer); 669 cv_pixel_buffer);
582 } else { 670 } else {
583 AVSampleBufferDisplayLayerEnqueueIOSurface(av_layer, io_surface); 671 AVSampleBufferDisplayLayerEnqueueIOSurface(av_layer, io_surface);
584 } 672 }
585 } 673 }
586 } else { 674 } else {
587 if (update_contents) { 675 if (update_contents) {
588 [ca_layer setContents:static_cast<id>(io_surface.get())]; 676 if (io_surface) {
677 [ca_layer setContents:static_cast<id>(io_surface.get())];
678 } else if (solid_color_contents) {
679 [ca_layer setContents:solid_color_contents->GetContents()];
680 } else {
681 [ca_layer setContents:nil];
682 }
589 if ([ca_layer respondsToSelector:(@selector(setContentsScale:))]) 683 if ([ca_layer respondsToSelector:(@selector(setContentsScale:))])
590 [ca_layer setContentsScale:scale_factor]; 684 [ca_layer setContentsScale:scale_factor];
591 } 685 }
592 if (update_contents_rect) 686 if (update_contents_rect)
593 [ca_layer setContentsRect:contents_rect.ToCGRect()]; 687 [ca_layer setContentsRect:contents_rect.ToCGRect()];
594 } 688 }
595 if (update_rect) { 689 if (update_rect) {
596 gfx::RectF dip_rect = gfx::RectF(rect); 690 gfx::RectF dip_rect = gfx::RectF(rect);
597 dip_rect.Scale(1 / scale_factor); 691 dip_rect.Scale(1 / scale_factor);
598 [ca_layer setPosition:CGPointMake(dip_rect.x(), dip_rect.y())]; 692 [ca_layer setPosition:CGPointMake(dip_rect.x(), dip_rect.y())];
(...skipping 20 matching lines...) Expand all
619 } 713 }
620 714
621 static bool show_borders = base::CommandLine::ForCurrentProcess()->HasSwitch( 715 static bool show_borders = base::CommandLine::ForCurrentProcess()->HasSwitch(
622 switches::kShowMacOverlayBorders); 716 switches::kShowMacOverlayBorders);
623 if (show_borders) { 717 if (show_borders) {
624 base::ScopedCFTypeRef<CGColorRef> color; 718 base::ScopedCFTypeRef<CGColorRef> color;
625 if (update_anything) { 719 if (update_anything) {
626 if (use_av_layer) { 720 if (use_av_layer) {
627 // Yellow represents an AV layer that changed this frame. 721 // Yellow represents an AV layer that changed this frame.
628 color.reset(CGColorCreateGenericRGB(1, 1, 0, 1)); 722 color.reset(CGColorCreateGenericRGB(1, 1, 0, 1));
723 } else if (io_surface) {
724 // Magenta represents a CALayer that changed this frame.
725 color.reset(CGColorCreateGenericRGB(1, 0, 1, 1));
726 } else if (solid_color_contents) {
727 // Cyan represents a solid color IOSurface-backed layer.
728 color.reset(CGColorCreateGenericRGB(0, 1, 1, 1));
629 } else { 729 } else {
630 // Pink represents a CALayer that changed this frame. 730 // Red represents a solid color layer.
631 color.reset(CGColorCreateGenericRGB(1, 0, 1, 1)); 731 color.reset(CGColorCreateGenericRGB(1, 0, 0, 1));
632 } 732 }
633 } else { 733 } else {
634 // Grey represents a CALayer that has not changed. 734 // Grey represents a CALayer that has not changed.
635 color.reset(CGColorCreateGenericRGB(0.5, 0.5, 0.5, 1)); 735 color.reset(CGColorCreateGenericRGB(0.5, 0.5, 0.5, 1));
636 } 736 }
637 [ca_layer setBorderWidth:1]; 737 [ca_layer setBorderWidth:1];
638 [ca_layer setBorderColor:color]; 738 [ca_layer setBorderColor:color];
639 } 739 }
640 } 740 }
641 741
642 } // namespace ui 742 } // namespace ui
OLDNEW
« no previous file with comments | « ui/accelerated_widget_mac/ca_renderer_layer_tree.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698