Skip to content

Commit

Permalink
SET: Allow an element to be specified multiple times as shared.
Browse files Browse the repository at this point in the history
This patch allows an element to be specified as shared multiple times.
This was already possible in the API, but we didn't plumb sufficient
information to viz to let it take advantage of it.

Also adds a (manual) test to exercise this behavior.

R=wangxianzhu@chromium.org

Bug: 1174141
Change-Id: I0e7da0889297e96d0ddafa66ae736055a987f5ec
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2844997
Commit-Queue: vmpstr <vmpstr@chromium.org>
Reviewed-by: Xianzhu Wang <wangxianzhu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#876233}
  • Loading branch information
vmpstr authored and Chromium LUCI CQ committed Apr 26, 2021
1 parent 3b5de6c commit d217f49
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 14 deletions.
1 change: 1 addition & 0 deletions cc/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ cc_component("cc") {
"benchmarks/unittest_only_benchmark_impl.h",
"document_transition/document_transition_request.cc",
"document_transition/document_transition_request.h",
"document_transition/document_transition_shared_element_id.cc",
"document_transition/document_transition_shared_element_id.h",
"input/actively_scrolling_type.h",
"input/browser_controls_offset_manager.cc",
Expand Down
10 changes: 8 additions & 2 deletions cc/document_transition/document_transition_request.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "cc/document_transition/document_transition_request.h"

#include <algorithm>
#include <map>
#include <memory>
#include <sstream>
Expand Down Expand Up @@ -114,8 +115,13 @@ DocumentTransitionRequest::ConstructDirective(
shared_element_render_pass_id_map) const {
std::vector<viz::CompositorRenderPassId> shared_passes(shared_element_count_);
for (uint32_t i = 0; i < shared_passes.size(); ++i) {
auto it = shared_element_render_pass_id_map.find(
DocumentTransitionSharedElementId{document_tag_, i});
auto it = std::find_if(
shared_element_render_pass_id_map.begin(),
shared_element_render_pass_id_map.end(),
[this, i](const std::pair<const DocumentTransitionSharedElementId,
viz::CompositorRenderPassId>& value) {
return value.first.Matches(document_tag_, i);
});
if (it == shared_element_render_pass_id_map.end())
continue;
shared_passes[i] = it->second;
Expand Down
38 changes: 38 additions & 0 deletions cc/document_transition/document_transition_shared_element_id.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright 2021 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/document_transition/document_transition_shared_element_id.h"

#include "base/check_op.h"
#include "base/containers/flat_set.h"

namespace cc {

DocumentTransitionSharedElementId::DocumentTransitionSharedElementId() =
default;

DocumentTransitionSharedElementId::DocumentTransitionSharedElementId(
uint32_t document_tag)
: document_tag_(document_tag) {}

DocumentTransitionSharedElementId::DocumentTransitionSharedElementId(
DocumentTransitionSharedElementId&&) = default;

DocumentTransitionSharedElementId::DocumentTransitionSharedElementId(
const DocumentTransitionSharedElementId&) = default;

DocumentTransitionSharedElementId::~DocumentTransitionSharedElementId() =
default;

void DocumentTransitionSharedElementId::AddIndex(uint32_t index) {
DCHECK_NE(document_tag_, 0u);
element_indices_.insert(index);
}

bool DocumentTransitionSharedElementId::Matches(uint32_t document_tag,
uint32_t index) const {
return document_tag_ == document_tag && element_indices_.count(index) != 0;
}

} // namespace cc
42 changes: 34 additions & 8 deletions cc/document_transition/document_transition_shared_element_id.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,53 @@

#include <tuple>

#include "base/containers/flat_set.h"
#include "cc/cc_export.h"

namespace cc {

struct DocumentTransitionSharedElementId {
uint32_t document_tag = 0u;
uint32_t element_index = 0u;
class CC_EXPORT DocumentTransitionSharedElementId {
public:
DocumentTransitionSharedElementId();
explicit DocumentTransitionSharedElementId(uint32_t document_tag);
DocumentTransitionSharedElementId(const DocumentTransitionSharedElementId&);
DocumentTransitionSharedElementId(DocumentTransitionSharedElementId&&);
~DocumentTransitionSharedElementId();

// Add a shared index to this id. It must have a valid document tag.
void AddIndex(uint32_t index);

// Returns true if the document tag matches this id and the index is in the
// list of indices for this id.
bool Matches(uint32_t document_tag, uint32_t index) const;

DocumentTransitionSharedElementId& operator=(
DocumentTransitionSharedElementId&&) = default;

DocumentTransitionSharedElementId& operator=(
const DocumentTransitionSharedElementId&) = default;

bool operator==(const DocumentTransitionSharedElementId& other) const {
return element_index == other.element_index &&
document_tag == other.document_tag;
return element_indices_ == other.element_indices_ &&
document_tag_ == other.document_tag_;
}

bool operator!=(const DocumentTransitionSharedElementId& other) const {
return !(*this == other);
}

bool operator<(const DocumentTransitionSharedElementId& other) const {
return std::tie(document_tag, element_index) <
std::tie(other.document_tag, other.element_index);
return std::tie(document_tag_, element_indices_) <
std::tie(other.document_tag_, other.element_indices_);
}

bool valid() const {
return document_tag_ != 0u && !element_indices_.empty();
}

bool valid() const { return document_tag != 0u; }
private:
uint32_t document_tag_ = 0u;
base::flat_set<uint32_t> element_indices_;
};

} // namespace cc
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,10 +243,13 @@ bool DocumentTransition::IsActiveElement(const Element* element) const {
DocumentTransitionSharedElementId DocumentTransition::GetSharedElementId(
const Element* element) const {
DCHECK(IsActiveElement(element));
wtf_size_t index = active_shared_elements_.Find(element);
DCHECK_NE(index, kNotFound);
return DocumentTransitionSharedElementId{document_tag_,
static_cast<uint32_t>(index)};
DocumentTransitionSharedElementId result(document_tag_);
for (wtf_size_t i = 0; i < active_shared_elements_.size(); ++i) {
if (active_shared_elements_[i] == element)
result.AddIndex(i);
}
DCHECK(result.valid());
return result;
}

void DocumentTransition::VerifySharedElements() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<!DOCTYPE html>
<html>
<title>Shared transitions: repeated elements (one -> two elements and back)</title>
<link rel="help" href="https://github.com/vmpstr/shared-element-transitions">
<link rel="author" href="mailto:vmpstr@chromium.org">

<style>
body {
background: lightpink;
}

#container {
width: max-content;
position: relative;
}

.hidden { display: none; }

.shape {
width: 100px;
height: 100px;
border-radius: 50%;
border: 1px solid black;
position: absolute;
contain: paint;
}

#yellow {
background: yellow;
left: 300px;
top: 50px;
}
#green {
background: green;
left: 50px;
top: 150px;
}
#blue {
background: blue;
left: 300px;
top: 250px;
}
</style>

<input id=toggle type=button value="Toggle!"></input>
<span>One shape becomes two and vice versa</span>
<div id=green class=shape></div>
<div id=blue class="shape hidden"></div>
<div id=yellow class="shape hidden"></div>

<script>
function visibleSharedElements() {
if (green.classList.contains("hidden")) {
return [blue, yellow];
} else {
return [green, green];
}
}

async function runAnimation() {
await document.documentTransition.prepare({
rootTransition: "none",
sharedElements: visibleSharedElements()
});

green.classList.toggle("hidden");
blue.classList.toggle("hidden");
yellow.classList.toggle("hidden");

await document.documentTransition.start({
sharedElements: visibleSharedElements()
});
}

function init() {
toggle.addEventListener("click", runAnimation);
}
onload = init;
</script>

0 comments on commit d217f49

Please sign in to comment.