blob: 70a33b11790c0f9d38772fc9d8128926b65d3e8e [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "cc/surfaces/referenced_surface_tracker.h"
#include <memory>
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "cc/surfaces/frame_sink_id.h"
#include "cc/surfaces/surface_id.h"
#include "cc/surfaces/surface_reference.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::UnorderedElementsAre;
using testing::IsEmpty;
using testing::SizeIs;
namespace cc {
namespace test {
namespace {
constexpr FrameSinkId kParentFrameSink(2, 1);
constexpr FrameSinkId kChildFrameSink1(65563, 1);
constexpr FrameSinkId kChildFrameSink2(65564, 1);
SurfaceId MakeSurfaceId(const FrameSinkId& frame_sink_id, uint32_t local_id) {
return SurfaceId(
frame_sink_id,
LocalSurfaceId(local_id, base::UnguessableToken::Deserialize(0, 1u)));
}
} // namespace
class ReferencedSurfaceTrackerTest : public testing::Test {
public:
ReferencedSurfaceTrackerTest() {}
~ReferencedSurfaceTrackerTest() override {}
ReferencedSurfaceTracker& tracker() { return *tracker_; }
// testing::Test:
void SetUp() override {
testing::Test::SetUp();
tracker_ = base::MakeUnique<ReferencedSurfaceTracker>(kParentFrameSink);
}
void TearDown() override { tracker_.reset(); }
private:
std::unique_ptr<ReferencedSurfaceTracker> tracker_;
DISALLOW_COPY_AND_ASSIGN(ReferencedSurfaceTrackerTest);
};
TEST_F(ReferencedSurfaceTrackerTest, SetCurrentSurfaceId) {
const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
// Initially current_surface_id() should be invalid.
EXPECT_FALSE(tracker().current_surface_id().is_valid());
// After setting current SurfaceId then current_surface_id() should be valid.
tracker().UpdateReferences(parent_id.local_surface_id(), nullptr, nullptr);
EXPECT_EQ(parent_id, tracker().current_surface_id());
}
TEST_F(ReferencedSurfaceTrackerTest, RefSurface) {
const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
const SurfaceReference reference(parent_id, child_id1);
// First frame has a reference to |child_id1|, check that reference is added.
std::vector<SurfaceId> active_referenced_surfaces = {child_id1};
tracker().UpdateReferences(parent_id.local_surface_id(),
&active_referenced_surfaces,
nullptr /* pending_referenced_surfaces */);
EXPECT_THAT(tracker().references_to_add(), UnorderedElementsAre(reference));
EXPECT_THAT(tracker().references_to_remove(), IsEmpty());
}
TEST_F(ReferencedSurfaceTrackerTest, NoChangeToReferences) {
const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
const SurfaceReference reference(parent_id, child_id1);
// First frame has a reference to |child_id1|, check that reference is added.
std::vector<SurfaceId> active_referenced_surfaces = {child_id1};
tracker().UpdateReferences(parent_id.local_surface_id(),
&active_referenced_surfaces,
nullptr /* pending_referenced_surfaces */);
EXPECT_THAT(tracker().references_to_remove(), IsEmpty());
EXPECT_THAT(tracker().references_to_add(), UnorderedElementsAre(reference));
// Second frame has same reference, check that no references are added or
// removed.
tracker().UpdateReferences(parent_id.local_surface_id(),
&active_referenced_surfaces,
nullptr /* pending_referenced_surfaces */);
EXPECT_THAT(tracker().references_to_remove(), IsEmpty());
EXPECT_THAT(tracker().references_to_add(), IsEmpty());
}
TEST_F(ReferencedSurfaceTrackerTest, UnrefSurface) {
const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
const SurfaceReference reference(parent_id, child_id1);
std::vector<SurfaceId> active_referenced_surfaces = {child_id1};
tracker().UpdateReferences(parent_id.local_surface_id(),
&active_referenced_surfaces,
nullptr /* pending_referenced_surfaces */);
// Second frame no longer references |child_id1|, check that reference to is
// removed.
tracker().UpdateReferences(parent_id.local_surface_id(),
nullptr /* active_referenced_surfaces */,
nullptr /* pending_referenced_surfaces */);
EXPECT_THAT(tracker().references_to_add(), IsEmpty());
EXPECT_THAT(tracker().references_to_remove(),
UnorderedElementsAre(reference));
}
TEST_F(ReferencedSurfaceTrackerTest, RefNewSurfaceForFrameSink) {
const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
const SurfaceId child_id1_first = MakeSurfaceId(kChildFrameSink1, 1);
const SurfaceId child_id1_second = MakeSurfaceId(kChildFrameSink1, 2);
const SurfaceReference reference_first(parent_id, child_id1_first);
const SurfaceReference reference_second(parent_id, child_id1_second);
// First frame has reference to |child_id1_first|.
std::vector<SurfaceId> active_referenced_surfaces1 = {child_id1_first};
tracker().UpdateReferences(parent_id.local_surface_id(),
&active_referenced_surfaces1,
nullptr /* pending_referenced_surfaces */);
EXPECT_THAT(tracker().references_to_add(),
UnorderedElementsAre(reference_first));
// Second frame has reference to |child_id1_second| which has the same
// FrameSinkId but different LocalSurfaceId. Check that first reference is
// removed and second reference is added.
std::vector<SurfaceId> active_referenced_surfaces2 = {child_id1_second};
tracker().UpdateReferences(parent_id.local_surface_id(),
&active_referenced_surfaces2,
nullptr /* pending_referenced_surfaces */);
EXPECT_THAT(tracker().references_to_remove(),
UnorderedElementsAre(reference_first));
EXPECT_THAT(tracker().references_to_add(),
UnorderedElementsAre(reference_second));
}
TEST_F(ReferencedSurfaceTrackerTest, UpdateParentSurfaceId) {
const SurfaceId parent_id_first = MakeSurfaceId(kParentFrameSink, 1);
const SurfaceId parent_id_second = MakeSurfaceId(kParentFrameSink, 2);
const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
const SurfaceReference reference(parent_id_second, child_id1);
// First frame references |child_id1|.
std::vector<SurfaceId> active_referenced_surfaces = {child_id1};
tracker().UpdateReferences(parent_id_first.local_surface_id(),
&active_referenced_surfaces,
nullptr /* pending_referenced_surfaces */);
EXPECT_THAT(tracker().references_to_add(), SizeIs(1));
// Second frame still reference |child_id1| but the parent SurfaceId has
// changed. The new parent SurfaceId should have a reference added to
// |child_id1|.
tracker().UpdateReferences(parent_id_second.local_surface_id(),
&active_referenced_surfaces,
nullptr /* pending_referenced_surfaces */);
EXPECT_THAT(tracker().references_to_add(), UnorderedElementsAre(reference));
EXPECT_THAT(tracker().references_to_remove(), IsEmpty());
}
TEST_F(ReferencedSurfaceTrackerTest, RefTwoThenUnrefOneSurface) {
const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink2, 2);
const SurfaceReference reference1(parent_id, child_id1);
const SurfaceReference reference2(parent_id, child_id2);
// First frame references both surfaces.
std::vector<SurfaceId> active_referenced_surfaces1 = {child_id1, child_id2};
tracker().UpdateReferences(parent_id.local_surface_id(),
&active_referenced_surfaces1,
nullptr /* pending_referenced_surfaces */);
EXPECT_THAT(tracker().references_to_add(),
UnorderedElementsAre(reference1, reference2));
// Second frame references only |child_id2|, check that reference to
// |child_id1| is removed.
std::vector<SurfaceId> active_referenced_surfaces2 = {child_id2};
tracker().UpdateReferences(parent_id.local_surface_id(),
&active_referenced_surfaces2,
nullptr /* pending_referenced_surfaces */);
EXPECT_THAT(tracker().references_to_remove(),
UnorderedElementsAre(reference1));
EXPECT_THAT(tracker().references_to_add(), IsEmpty());
}
} // namespace test
} // namespace cc