Commit f33642d1 authored by ccameron's avatar ccameron Committed by Commit bot

Mac video: Add blacklist entry for AVSampleBufferDisplayLayer

This leaks IOSurfaces on 10.9. Include 10.10 in the blacklist because it
has not been sufficiently tested.

BUG=632178
CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.linux:linux_optional_gpu_tests_rel;master.tryserver.chromium.mac:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel

Review-Url: https://codereview.chromium.org/2366433002
Cr-Commit-Position: refs/heads/master@{#420543}
parent 98219047
......@@ -19,7 +19,7 @@ const char kGpuDriverBugListJson[] = LONG_STRING_CONST(
{
"name": "gpu driver bug list",
// Please update the version number whenever you change this file.
"version": "8.99",
"version": "9.00",
"entries": [
{
"id": 1,
......@@ -2003,6 +2003,21 @@ LONG_STRING_CONST(
"features": [
"rewrite_do_while_loops"
]
},
{
"id": 188,
"description": "AVSampleBufferDisplayLayer leaks IOSurfaces on 10.9.",
"cr_bugs": [632178],
"os": {
"type": "macosx",
"version": {
"op": "<=",
"value": "10.10"
}
},
"features": [
"disable_av_sample_buffer_display_layer"
]
}
]
// Please update the version number at beginning of this file whenever you
......
......@@ -33,6 +33,8 @@
disable_angle_instanced_arrays) \
GPU_OP(DISABLE_ASYNC_READPIXELS, \
disable_async_readpixels) \
GPU_OP(DISABLE_AV_SAMPLE_BUFFER_DISPLAY_LAYER, \
disable_av_sample_buffer_display_layer) \
GPU_OP(DISABLE_BLEND_EQUATION_ADVANCED, \
disable_blend_equation_advanced) \
GPU_OP(DISABLE_CHROMIUM_FRAMEBUFFER_MULTISAMPLE, \
......
......@@ -75,8 +75,14 @@ ImageTransportSurfaceOverlayMac::ImageTransportSurfaceOverlayMac(
scale_factor_(1),
gl_renderer_id_(0) {
ui::GpuSwitchingManager::GetInstance()->AddObserver(this);
ca_layer_tree_coordinator_.reset(
new ui::CALayerTreeCoordinator(use_remote_layer_api_));
bool disable_av_sample_buffer_display_layer =
stub_->GetFeatureInfo()
->workarounds()
.disable_av_sample_buffer_display_layer;
ca_layer_tree_coordinator_.reset(new ui::CALayerTreeCoordinator(
use_remote_layer_api_, !disable_av_sample_buffer_display_layer));
}
ImageTransportSurfaceOverlayMac::~ImageTransportSurfaceOverlayMac() {
......
......@@ -21,7 +21,8 @@ namespace ui {
// to the browser process in https://crbug.com/604052.
class ACCELERATED_WIDGET_MAC_EXPORT CALayerTreeCoordinator {
public:
explicit CALayerTreeCoordinator(bool allow_remote_layers);
explicit CALayerTreeCoordinator(bool allow_remote_layers,
bool allow_av_sample_buffer_display_layer);
~CALayerTreeCoordinator();
// Set the composited frame's size.
......@@ -56,7 +57,8 @@ class ACCELERATED_WIDGET_MAC_EXPORT CALayerTreeCoordinator {
IOSurfaceRef GetIOSurfaceForDisplay();
private:
bool allow_remote_layers_ = true;
const bool allow_remote_layers_ = true;
const bool allow_av_sample_buffer_display_layer_ = true;
gfx::Size pixel_size_;
float scale_factor_ = 1;
......
......@@ -11,15 +11,21 @@
namespace ui {
CALayerTreeCoordinator::CALayerTreeCoordinator(bool allow_remote_layers)
: allow_remote_layers_(allow_remote_layers) {
CALayerTreeCoordinator::CALayerTreeCoordinator(
bool allow_remote_layers,
bool allow_av_sample_buffer_display_layer)
: allow_remote_layers_(allow_remote_layers),
allow_av_sample_buffer_display_layer_(
allow_av_sample_buffer_display_layer) {
if (allow_remote_layers_) {
root_ca_layer_.reset([[CALayer alloc] init]);
[root_ca_layer_ setGeometryFlipped:YES];
[root_ca_layer_ setOpaque:YES];
fullscreen_low_power_layer_.reset(
[[AVSampleBufferDisplayLayer alloc] init]);
if (allow_av_sample_buffer_display_layer_) {
fullscreen_low_power_layer_.reset(
[[AVSampleBufferDisplayLayer alloc] init]);
}
}
}
......@@ -55,7 +61,8 @@ CARendererLayerTree* CALayerTreeCoordinator::GetPendingCARendererLayerTree() {
"specified, but not both.";
}
if (!pending_ca_renderer_layer_tree_)
pending_ca_renderer_layer_tree_.reset(new CARendererLayerTree);
pending_ca_renderer_layer_tree_.reset(
new CARendererLayerTree(allow_av_sample_buffer_display_layer_));
return pending_ca_renderer_layer_tree_.get();
}
......
......@@ -74,7 +74,20 @@ void UpdateCALayerTree(std::unique_ptr<ui::CARendererLayerTree>& ca_layer_tree,
CALayerProperties* properties,
CALayer* superlayer) {
std::unique_ptr<ui::CARendererLayerTree> new_ca_layer_tree(
new ui::CARendererLayerTree);
new ui::CARendererLayerTree(true));
bool result = ScheduleCALayer(new_ca_layer_tree.get(), properties);
EXPECT_TRUE(result);
new_ca_layer_tree->CommitScheduledCALayers(
superlayer, std::move(ca_layer_tree), properties->scale_factor);
std::swap(new_ca_layer_tree, ca_layer_tree);
}
void UpdateCALayerTreeWithAVDisabled(
std::unique_ptr<ui::CARendererLayerTree>& ca_layer_tree,
CALayerProperties* properties,
CALayer* superlayer) {
std::unique_ptr<ui::CARendererLayerTree> new_ca_layer_tree(
new ui::CARendererLayerTree(false));
bool result = ScheduleCALayer(new_ca_layer_tree.get(), properties);
EXPECT_TRUE(result);
new_ca_layer_tree->CommitScheduledCALayers(
......@@ -118,7 +131,7 @@ TEST_F(CALayerTreeTest, PropertyUpdates) {
// Validate the initial values.
{
std::unique_ptr<ui::CARendererLayerTree> new_ca_layer_tree(
new ui::CARendererLayerTree);
new ui::CARendererLayerTree(true));
UpdateCALayerTree(ca_layer_tree, &properties, superlayer_);
......@@ -472,7 +485,7 @@ TEST_F(CALayerTreeTest, SplitSortingContextZero) {
// Schedule and commit the layers.
std::unique_ptr<ui::CARendererLayerTree> ca_layer_tree(
new ui::CARendererLayerTree);
new ui::CARendererLayerTree(true));
for (size_t i = 0; i < 5; ++i) {
properties.gl_image = gl_images[i];
properties.transform = transforms[i];
......@@ -555,7 +568,7 @@ TEST_F(CALayerTreeTest, SortingContexts) {
// Schedule and commit the layers.
std::unique_ptr<ui::CARendererLayerTree> ca_layer_tree(
new ui::CARendererLayerTree);
new ui::CARendererLayerTree(true));
for (size_t i = 0; i < 3; ++i) {
properties.sorting_context_id = sorting_context_ids[i];
properties.gl_image = gl_images[i];
......@@ -619,7 +632,7 @@ TEST_F(CALayerTreeTest, SortingContextMustHaveConsistentClip) {
};
std::unique_ptr<ui::CARendererLayerTree> ca_layer_tree(
new ui::CARendererLayerTree);
new ui::CARendererLayerTree(true));
// First send the various clip parameters to sorting context zero. This is
// legitimate.
for (size_t i = 0; i < 3; ++i) {
......@@ -762,6 +775,57 @@ TEST_F(CALayerTreeTest, AVLayer) {
}
}
// Ensure that blacklisting AVSampleBufferDisplayLayer works.
TEST_F(CALayerTreeTest, AVLayerBlacklist) {
CALayerProperties properties;
properties.gl_image = CreateGLImage(
gfx::Size(256, 256), gfx::BufferFormat::YUV_420_BIPLANAR, false);
std::unique_ptr<ui::CARendererLayerTree> ca_layer_tree;
CALayer* root_layer = nil;
CALayer* clip_and_sorting_layer = nil;
CALayer* transform_layer = nil;
CALayer* content_layer1 = nil;
CALayer* content_layer2 = nil;
{
UpdateCALayerTree(ca_layer_tree, &properties, superlayer_);
// Validate the tree structure.
EXPECT_EQ(1u, [[superlayer_ sublayers] count]);
root_layer = [[superlayer_ sublayers] objectAtIndex:0];
EXPECT_EQ(1u, [[root_layer sublayers] count]);
clip_and_sorting_layer = [[root_layer sublayers] objectAtIndex:0];
EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]);
transform_layer = [[clip_and_sorting_layer sublayers] objectAtIndex:0];
EXPECT_EQ(1u, [[transform_layer sublayers] count]);
content_layer1 = [[transform_layer sublayers] objectAtIndex:0];
// Validate the content layer.
EXPECT_TRUE([content_layer1
isKindOfClass:NSClassFromString(@"AVSampleBufferDisplayLayer")]);
}
{
UpdateCALayerTreeWithAVDisabled(ca_layer_tree, &properties, superlayer_);
// Validate the tree structure.
EXPECT_EQ(1u, [[superlayer_ sublayers] count]);
root_layer = [[superlayer_ sublayers] objectAtIndex:0];
EXPECT_EQ(1u, [[root_layer sublayers] count]);
clip_and_sorting_layer = [[root_layer sublayers] objectAtIndex:0];
EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]);
transform_layer = [[clip_and_sorting_layer sublayers] objectAtIndex:0];
EXPECT_EQ(1u, [[transform_layer sublayers] count]);
content_layer2 = [[transform_layer sublayers] objectAtIndex:0];
// Validate the content layer.
EXPECT_FALSE([content_layer2
isKindOfClass:NSClassFromString(@"AVSampleBufferDisplayLayer")]);
EXPECT_NE(content_layer1, content_layer2);
}
}
// Test fullscreen low power detection.
TEST_F(CALayerTreeTest, FullscreenLowPower) {
CALayerProperties properties;
......@@ -781,7 +845,7 @@ TEST_F(CALayerTreeTest, FullscreenLowPower) {
// Test a configuration with no background.
{
std::unique_ptr<ui::CARendererLayerTree> new_ca_layer_tree(
new ui::CARendererLayerTree);
new ui::CARendererLayerTree(true));
bool result = ScheduleCALayer(new_ca_layer_tree.get(), &properties);
EXPECT_TRUE(result);
new_ca_layer_tree->CommitScheduledCALayers(
......@@ -811,7 +875,7 @@ TEST_F(CALayerTreeTest, FullscreenLowPower) {
// Test a configuration with a black background.
{
std::unique_ptr<ui::CARendererLayerTree> new_ca_layer_tree(
new ui::CARendererLayerTree);
new ui::CARendererLayerTree(true));
bool result = ScheduleCALayer(new_ca_layer_tree.get(), &properties_black);
EXPECT_TRUE(result);
result = ScheduleCALayer(new_ca_layer_tree.get(), &properties);
......@@ -843,7 +907,7 @@ TEST_F(CALayerTreeTest, FullscreenLowPower) {
// Test a configuration with a white background. It will fail.
{
std::unique_ptr<ui::CARendererLayerTree> new_ca_layer_tree(
new ui::CARendererLayerTree);
new ui::CARendererLayerTree(true));
bool result = ScheduleCALayer(new_ca_layer_tree.get(), &properties_white);
EXPECT_TRUE(result);
result = ScheduleCALayer(new_ca_layer_tree.get(), &properties);
......@@ -875,7 +939,7 @@ TEST_F(CALayerTreeTest, FullscreenLowPower) {
// Test a configuration with a black foreground. It too will fail.
{
std::unique_ptr<ui::CARendererLayerTree> new_ca_layer_tree(
new ui::CARendererLayerTree);
new ui::CARendererLayerTree(true));
bool result = ScheduleCALayer(new_ca_layer_tree.get(), &properties);
EXPECT_TRUE(result);
result = ScheduleCALayer(new_ca_layer_tree.get(), &properties_black);
......
......@@ -32,7 +32,7 @@ struct CARendererLayerParams;
// https://docs.google.com/document/d/1DtSN9zzvCF44_FQPM7ie01UxGHagQ66zfF5L9HnigQY/edit?usp=sharing
class ACCELERATED_WIDGET_MAC_EXPORT CARendererLayerTree {
public:
CARendererLayerTree();
CARendererLayerTree(bool allow_av_sample_buffer_display_layer);
// This will remove all CALayers from this tree from their superlayer.
~CARendererLayerTree();
......@@ -63,6 +63,7 @@ class ACCELERATED_WIDGET_MAC_EXPORT CARendererLayerTree {
struct ClipAndSortingLayer;
struct TransformLayer;
struct ContentLayer;
friend struct ContentLayer;
struct RootLayer {
RootLayer();
......@@ -73,7 +74,8 @@ class ACCELERATED_WIDGET_MAC_EXPORT CARendererLayerTree {
// Append a new content layer, without modifying the actual CALayer
// structure.
bool AddContentLayer(const CARendererLayerParams& params);
bool AddContentLayer(CARendererLayerTree* tree,
const CARendererLayerParams& params);
// Allocate CALayers for this layer and its children, and set their
// properties appropriately. Re-use the CALayers from |old_layer| if
......@@ -99,7 +101,8 @@ class ACCELERATED_WIDGET_MAC_EXPORT CARendererLayerTree {
// See the behavior of RootLayer for the effects of these functions on the
// |ca_layer| member and |old_layer| argument.
~ClipAndSortingLayer();
void AddContentLayer(const CARendererLayerParams& params);
void AddContentLayer(CARendererLayerTree* tree,
const CARendererLayerParams& params);
void CommitToCA(CALayer* superlayer,
ClipAndSortingLayer* old_layer,
float scale_factor);
......@@ -121,7 +124,8 @@ class ACCELERATED_WIDGET_MAC_EXPORT CARendererLayerTree {
// See the behavior of RootLayer for the effects of these functions on the
// |ca_layer| member and |old_layer| argument.
~TransformLayer();
void AddContentLayer(const CARendererLayerParams& params);
void AddContentLayer(CARendererLayerTree* tree,
const CARendererLayerParams& params);
void CommitToCA(CALayer* superlayer,
TransformLayer* old_layer,
float scale_factor);
......@@ -134,7 +138,8 @@ class ACCELERATED_WIDGET_MAC_EXPORT CARendererLayerTree {
DISALLOW_COPY_AND_ASSIGN(TransformLayer);
};
struct ContentLayer {
ContentLayer(base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
ContentLayer(CARendererLayerTree* tree,
base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
base::ScopedCFTypeRef<CVPixelBufferRef> cv_pixel_buffer,
const gfx::RectF& contents_rect,
const gfx::Rect& rect,
......@@ -178,6 +183,7 @@ class ACCELERATED_WIDGET_MAC_EXPORT CARendererLayerTree {
RootLayer root_layer_;
float scale_factor_ = 1;
bool has_committed_ = false;
const bool allow_av_sample_buffer_display_layer_ = true;
private:
DISALLOW_COPY_AND_ASSIGN(CARendererLayerTree);
......
......@@ -129,7 +129,10 @@ bool AVSampleBufferDisplayLayerEnqueueIOSurface(
} // namespace
CARendererLayerTree::CARendererLayerTree() {}
CARendererLayerTree::CARendererLayerTree(
bool allow_av_sample_buffer_display_layer)
: allow_av_sample_buffer_display_layer_(
allow_av_sample_buffer_display_layer) {}
CARendererLayerTree::~CARendererLayerTree() {}
bool CARendererLayerTree::ScheduleCALayer(const CARendererLayerParams& params) {
......@@ -139,7 +142,7 @@ bool CARendererLayerTree::ScheduleCALayer(const CARendererLayerParams& params) {
LOG(ERROR) << "ScheduleCALayer called after CommitScheduledCALayers.";
return false;
}
return root_layer_.AddContentLayer(params);
return root_layer_.AddContentLayer(this, params);
}
void CARendererLayerTree::CommitScheduledCALayers(
......@@ -267,6 +270,7 @@ CARendererLayerTree::TransformLayer::~TransformLayer() {
}
CARendererLayerTree::ContentLayer::ContentLayer(
CARendererLayerTree* tree,
base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
base::ScopedCFTypeRef<CVPixelBufferRef> cv_pixel_buffer,
const gfx::RectF& contents_rect,
......@@ -311,7 +315,8 @@ CARendererLayerTree::ContentLayer::ContentLayer(
// Only allow 4:2:0 frames which fill the layer's contents to be promoted to
// AV layers.
if (IOSurfaceGetPixelFormat(io_surface) ==
if (tree->allow_av_sample_buffer_display_layer_ &&
IOSurfaceGetPixelFormat(io_surface) ==
kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange &&
contents_rect == gfx::RectF(0, 0, 1, 1)) {
use_av_layer = true;
......@@ -339,6 +344,7 @@ CARendererLayerTree::ContentLayer::~ContentLayer() {
}
bool CARendererLayerTree::RootLayer::AddContentLayer(
CARendererLayerTree* tree,
const CARendererLayerParams& params) {
bool needs_new_clip_and_sorting_layer = true;
......@@ -375,11 +381,12 @@ bool CARendererLayerTree::RootLayer::AddContentLayer(
params.is_clipped, params.clip_rect, params.sorting_context_id,
is_singleton_sorting_context));
}
clip_and_sorting_layers.back().AddContentLayer(params);
clip_and_sorting_layers.back().AddContentLayer(tree, params);
return true;
}
void CARendererLayerTree::ClipAndSortingLayer::AddContentLayer(
CARendererLayerTree* tree,
const CARendererLayerParams& params) {
bool needs_new_transform_layer = true;
if (!transform_layers.empty()) {
......@@ -389,10 +396,11 @@ void CARendererLayerTree::ClipAndSortingLayer::AddContentLayer(
}
if (needs_new_transform_layer)
transform_layers.push_back(TransformLayer(params.transform));
transform_layers.back().AddContentLayer(params);
transform_layers.back().AddContentLayer(tree, params);
}
void CARendererLayerTree::TransformLayer::AddContentLayer(
CARendererLayerTree* tree,
const CARendererLayerParams& params) {
base::ScopedCFTypeRef<IOSurfaceRef> io_surface;
base::ScopedCFTypeRef<CVPixelBufferRef> cv_pixel_buffer;
......@@ -405,7 +413,7 @@ void CARendererLayerTree::TransformLayer::AddContentLayer(
}
content_layers.push_back(
ContentLayer(io_surface, cv_pixel_buffer, params.contents_rect,
ContentLayer(tree, io_surface, cv_pixel_buffer, params.contents_rect,
params.rect, params.background_color, params.edge_aa_mask,
params.opacity, params.filter));
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment