Commit a002a087 authored by Ian Vollick's avatar Ian Vollick Committed by Commit Bot

[vr] Avoid some unnecessary work in UpdateWorldSpaceTransforms

Previously, we would do the local update unconditionally. With this
change, we keep track of a dirty bit for the world space transform as
well as a baked version of the local transform so we don't need to
call cc::TransformOperations::Apply repeatedly to realize the same
results.

Some elements have special conditions for the dirtiness of their local
transform, so I have also created a ShouldUpdateWorldSpaceTransform
function so that subclasses can customize this behavior. The reticle,
for example, is always dirty.

Bug: 828684
Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;master.tryserver.chromium.linux:linux_vr;master.tryserver.chromium.win:win_optional_gpu_tests_rel
Change-Id: I5b581a72d7caa39d47dcdc686d212879b3da3093
Reviewed-on: https://chromium-review.googlesource.com/995573Reviewed-by: default avatarTibor Goldschwendt <tiborg@chromium.org>
Commit-Queue: Ian Vollick <vollick@chromium.org>
Cr-Commit-Position: refs/heads/master@{#548075}
parent 597be546
...@@ -21,6 +21,7 @@ class Controller : public UiElement { ...@@ -21,6 +21,7 @@ class Controller : public UiElement {
void set_local_transform(const gfx::Transform& transform) { void set_local_transform(const gfx::Transform& transform) {
local_transform_ = transform; local_transform_ = transform;
set_world_space_transform_dirty();
} }
class Renderer : public BaseRenderer { class Renderer : public BaseRenderer {
......
...@@ -65,9 +65,12 @@ void Repositioner::SetEnabled(bool enabled) { ...@@ -65,9 +65,12 @@ void Repositioner::SetEnabled(bool enabled) {
void Repositioner::Reset() { void Repositioner::Reset() {
transform_.MakeIdentity(); transform_.MakeIdentity();
set_world_space_transform_dirty();
} }
void Repositioner::UpdateTransform(const gfx::Transform& head_pose) { void Repositioner::UpdateTransform(const gfx::Transform& head_pose) {
set_world_space_transform_dirty();
gfx::Vector3dF head_up = vr::GetUpVector(head_pose); gfx::Vector3dF head_up = vr::GetUpVector(head_pose);
gfx::Vector3dF head_forward = vr::GetForwardVector(head_pose); gfx::Vector3dF head_forward = vr::GetForwardVector(head_pose);
......
...@@ -56,6 +56,7 @@ void Resizer::SetEnabled(bool enabled) { ...@@ -56,6 +56,7 @@ void Resizer::SetEnabled(bool enabled) {
void Resizer::Reset() { void Resizer::Reset() {
transform_.MakeIdentity(); transform_.MakeIdentity();
set_world_space_transform_dirty();
t_ = initial_t_ = kDefaultFraction; t_ = initial_t_ = kDefaultFraction;
} }
...@@ -66,6 +67,7 @@ void Resizer::UpdateTransform(const gfx::Transform& head_pose) { ...@@ -66,6 +67,7 @@ void Resizer::UpdateTransform(const gfx::Transform& head_pose) {
gfx::Tween::FloatValueBetween(t_, kMinResizerScale, kMaxResizerScale); gfx::Tween::FloatValueBetween(t_, kMinResizerScale, kMaxResizerScale);
transform_.MakeIdentity(); transform_.MakeIdentity();
transform_.Scale(scale, scale); transform_.Scale(scale, scale);
set_world_space_transform_dirty();
} }
bool Resizer::OnBeginFrame(const base::TimeTicks& time, bool Resizer::OnBeginFrame(const base::TimeTicks& time,
......
...@@ -183,4 +183,9 @@ gfx::Transform Reticle::GetTargetLocalTransform() const { ...@@ -183,4 +183,9 @@ gfx::Transform Reticle::GetTargetLocalTransform() const {
return LocalTransform(); return LocalTransform();
} }
bool Reticle::ShouldUpdateWorldSpaceTransform(
bool parent_transform_changed) const {
return true;
}
} // namespace vr } // namespace vr
...@@ -49,6 +49,8 @@ class Reticle : public UiElement { ...@@ -49,6 +49,8 @@ class Reticle : public UiElement {
const CameraModel& model) const final; const CameraModel& model) const final;
gfx::Transform LocalTransform() const final; gfx::Transform LocalTransform() const final;
gfx::Transform GetTargetLocalTransform() const final; gfx::Transform GetTargetLocalTransform() const final;
bool ShouldUpdateWorldSpaceTransform(
bool parent_transform_changed) const final;
gfx::Point3F origin_; gfx::Point3F origin_;
gfx::Point3F target_; gfx::Point3F target_;
......
...@@ -45,6 +45,7 @@ bool ScaledDepthAdjuster::OnBeginFrame(const base::TimeTicks& time, ...@@ -45,6 +45,7 @@ bool ScaledDepthAdjuster::OnBeginFrame(const base::TimeTicks& time,
float z = -o.z() + delta_z_; float z = -o.z() + delta_z_;
transform_.Scale3d(z, z, z); transform_.Scale3d(z, z, z);
transform_.Translate3d(0, 0, -1); transform_.Translate3d(0, 0, -1);
set_world_space_transform_dirty();
return true; return true;
} }
......
...@@ -302,15 +302,29 @@ void UiElement::SetLayoutOffset(float x, float y) { ...@@ -302,15 +302,29 @@ void UiElement::SetLayoutOffset(float x, float y) {
} else if (y_centering() == BOTTOM) { } else if (y_centering() == BOTTOM) {
y += size_.height() / 2; y += size_.height() / 2;
} }
if (x == layout_offset_.at(0).translate.x &&
y == layout_offset_.at(0).translate.y &&
!IsAnimatingProperty(LAYOUT_OFFSET)) {
return;
}
cc::TransformOperations operations = layout_offset_; cc::TransformOperations operations = layout_offset_;
cc::TransformOperation& op = operations.at(0); cc::TransformOperation& op = operations.at(0);
op.translate = {x, y, 0}; op.translate = {x, y, 0};
op.Bake(); op.Bake();
animation_.TransitionTransformOperationsTo(last_frame_time_, LAYOUT_OFFSET, animation_.TransitionTransformOperationsTo(last_frame_time_, LAYOUT_OFFSET,
transform_operations_, operations); layout_offset_, operations);
} }
void UiElement::SetTranslate(float x, float y, float z) { void UiElement::SetTranslate(float x, float y, float z) {
if (x == transform_operations_.at(kTranslateIndex).translate.x &&
y == transform_operations_.at(kTranslateIndex).translate.y &&
z == transform_operations_.at(kTranslateIndex).translate.z &&
!IsAnimatingProperty(TRANSFORM)) {
return;
}
cc::TransformOperations operations = transform_operations_; cc::TransformOperations operations = transform_operations_;
cc::TransformOperation& op = operations.at(kTranslateIndex); cc::TransformOperation& op = operations.at(kTranslateIndex);
op.translate = {x, y, z}; op.translate = {x, y, z};
...@@ -320,16 +334,33 @@ void UiElement::SetTranslate(float x, float y, float z) { ...@@ -320,16 +334,33 @@ void UiElement::SetTranslate(float x, float y, float z) {
} }
void UiElement::SetRotate(float x, float y, float z, float radians) { void UiElement::SetRotate(float x, float y, float z, float radians) {
float degrees = gfx::RadToDeg(radians);
if (x == transform_operations_.at(kRotateIndex).rotate.axis.x &&
y == transform_operations_.at(kRotateIndex).rotate.axis.y &&
z == transform_operations_.at(kRotateIndex).rotate.axis.z &&
degrees == transform_operations_.at(kRotateIndex).rotate.angle &&
!IsAnimatingProperty(TRANSFORM)) {
return;
}
cc::TransformOperations operations = transform_operations_; cc::TransformOperations operations = transform_operations_;
cc::TransformOperation& op = operations.at(kRotateIndex); cc::TransformOperation& op = operations.at(kRotateIndex);
op.rotate.axis = {x, y, z}; op.rotate.axis = {x, y, z};
op.rotate.angle = gfx::RadToDeg(radians); op.rotate.angle = degrees;
op.Bake(); op.Bake();
animation_.TransitionTransformOperationsTo(last_frame_time_, TRANSFORM, animation_.TransitionTransformOperationsTo(last_frame_time_, TRANSFORM,
transform_operations_, operations); transform_operations_, operations);
} }
void UiElement::SetScale(float x, float y, float z) { void UiElement::SetScale(float x, float y, float z) {
if (x == transform_operations_.at(kScaleIndex).scale.x &&
y == transform_operations_.at(kScaleIndex).scale.y &&
z == transform_operations_.at(kScaleIndex).scale.z &&
!IsAnimatingProperty(TRANSFORM)) {
return;
}
cc::TransformOperations operations = transform_operations_; cc::TransformOperations operations = transform_operations_;
cc::TransformOperation& op = operations.at(kScaleIndex); cc::TransformOperation& op = operations.at(kScaleIndex);
op.scale = {x, y, z}; op.scale = {x, y, z};
...@@ -654,12 +685,17 @@ void UiElement::NotifyClientTransformOperationsAnimated( ...@@ -654,12 +685,17 @@ void UiElement::NotifyClientTransformOperationsAnimated(
} else { } else {
NOTREACHED(); NOTREACHED();
} }
local_transform_ = layout_offset_.Apply() * transform_operations_.Apply();
world_space_transform_dirty_ = true;
} }
void UiElement::NotifyClientSizeAnimated(const gfx::SizeF& size, void UiElement::NotifyClientSizeAnimated(const gfx::SizeF& size,
int target_property_id, int target_property_id,
cc::KeyframeModel* keyframe_model) { cc::KeyframeModel* keyframe_model) {
if (size_ == size)
return;
size_ = size; size_ = size;
world_space_transform_dirty_ = true;
} }
void UiElement::SetTransitionedProperties( void UiElement::SetTransitionedProperties(
...@@ -747,7 +783,10 @@ void UiElement::DoLayOutChildren() { ...@@ -747,7 +783,10 @@ void UiElement::DoLayOutChildren() {
bounds.Inset(-left_padding_, -bottom_padding_, -right_padding_, bounds.Inset(-left_padding_, -bottom_padding_, -right_padding_,
-top_padding_); -top_padding_);
bounds.set_origin(bounds.CenterPoint()); bounds.set_origin(bounds.CenterPoint());
if (local_origin_ != bounds.origin()) {
world_space_transform_dirty_ = true;
local_origin_ = bounds.origin(); local_origin_ = bounds.origin();
}
if (bounds.size() == GetTargetSize()) if (bounds.size() == GetTargetSize())
return; return;
...@@ -801,15 +840,18 @@ void UiElement::UpdateComputedOpacity() { ...@@ -801,15 +840,18 @@ void UiElement::UpdateComputedOpacity() {
updated_visibility_this_frame_ = IsVisible() != was_visible; updated_visibility_this_frame_ = IsVisible() != was_visible;
} }
void UiElement::UpdateWorldSpaceTransformRecursive() { void UiElement::UpdateWorldSpaceTransformRecursive(bool parent_changed) {
bool changed = false;
if (ShouldUpdateWorldSpaceTransform(parent_changed)) {
gfx::Transform transform; gfx::Transform transform;
transform.Translate(local_origin_.x(), local_origin_.y()); transform.Translate(local_origin_.x(), local_origin_.y());
if (!size_.IsEmpty()) { if (!size_.IsEmpty()) {
transform.Scale(size_.width(), size_.height()); transform.Scale(size_.width(), size_.height());
} }
// Compute an inheritable transformation that can be applied to this element, // Compute an inheritable transformation that can be applied to this
// and it's children, if applicable. // element, and it's children, if applicable.
gfx::Transform inheritable = LocalTransform(); gfx::Transform inheritable = LocalTransform();
if (parent_) { if (parent_) {
...@@ -819,17 +861,19 @@ void UiElement::UpdateWorldSpaceTransformRecursive() { ...@@ -819,17 +861,19 @@ void UiElement::UpdateWorldSpaceTransformRecursive() {
transform.ConcatTransform(inheritable); transform.ConcatTransform(inheritable);
set_world_space_transform(transform); set_world_space_transform(transform);
set_inheritable_transform(inheritable); set_inheritable_transform(inheritable);
set_update_phase(kUpdatedWorldSpaceTransform); changed = true;
}
set_update_phase(kUpdatedWorldSpaceTransform);
for (auto& child : children_) { for (auto& child : children_) {
child->UpdateWorldSpaceTransformRecursive(); child->UpdateWorldSpaceTransformRecursive(changed);
} }
OnUpdatedWorldSpaceTransform(); OnUpdatedWorldSpaceTransform();
} }
gfx::Transform UiElement::LocalTransform() const { gfx::Transform UiElement::LocalTransform() const {
return layout_offset_.Apply() * transform_operations_.Apply(); return local_transform_;
} }
gfx::Transform UiElement::GetTargetLocalTransform() const { gfx::Transform UiElement::GetTargetLocalTransform() const {
...@@ -840,4 +884,9 @@ const Sounds& UiElement::GetSounds() const { ...@@ -840,4 +884,9 @@ const Sounds& UiElement::GetSounds() const {
return sounds_; return sounds_;
} }
bool UiElement::ShouldUpdateWorldSpaceTransform(
bool parent_transform_changed) const {
return parent_transform_changed || world_space_transform_dirty_;
}
} // namespace vr } // namespace vr
...@@ -337,6 +337,7 @@ class UiElement : public cc::AnimationTarget { ...@@ -337,6 +337,7 @@ class UiElement : public cc::AnimationTarget {
const gfx::Transform& world_space_transform() const; const gfx::Transform& world_space_transform() const;
void set_world_space_transform(const gfx::Transform& transform) { void set_world_space_transform(const gfx::Transform& transform) {
world_space_transform_ = transform; world_space_transform_ = transform;
world_space_transform_dirty_ = false;
} }
gfx::Transform ComputeTargetWorldSpaceTransform() const; gfx::Transform ComputeTargetWorldSpaceTransform() const;
...@@ -413,7 +414,7 @@ class UiElement : public cc::AnimationTarget { ...@@ -413,7 +414,7 @@ class UiElement : public cc::AnimationTarget {
virtual gfx::Transform GetTargetLocalTransform() const; virtual gfx::Transform GetTargetLocalTransform() const;
void UpdateComputedOpacity(); void UpdateComputedOpacity();
void UpdateWorldSpaceTransformRecursive(); void UpdateWorldSpaceTransformRecursive(bool parent_changed);
std::vector<std::unique_ptr<UiElement>>& children() { return children_; } std::vector<std::unique_ptr<UiElement>>& children() { return children_; }
const std::vector<std::unique_ptr<UiElement>>& children() const { const std::vector<std::unique_ptr<UiElement>>& children() const {
...@@ -492,6 +493,13 @@ class UiElement : public cc::AnimationTarget { ...@@ -492,6 +493,13 @@ class UiElement : public cc::AnimationTarget {
virtual const Sounds& GetSounds() const; virtual const Sounds& GetSounds() const;
virtual bool ShouldUpdateWorldSpaceTransform(
bool parent_transform_changed) const;
void set_world_space_transform_dirty() {
world_space_transform_dirty_ = true;
}
EventHandlers event_handlers_; EventHandlers event_handlers_;
private: private:
...@@ -601,12 +609,16 @@ class UiElement : public cc::AnimationTarget { ...@@ -601,12 +609,16 @@ class UiElement : public cc::AnimationTarget {
// the translation, but leave the rotation and scale in tact). // the translation, but leave the rotation and scale in tact).
cc::TransformOperations transform_operations_; cc::TransformOperations transform_operations_;
// This is a cached version of the local transform.
gfx::Transform local_transform_;
// This is set by the parent and is combined into LocalTransform() // This is set by the parent and is combined into LocalTransform()
cc::TransformOperations layout_offset_; cc::TransformOperations layout_offset_;
// This is the combined, local to world transform. It includes // This is the combined, local to world transform. It includes
// |inheritable_transform_|, |transform_|, and anchoring adjustments. // |inheritable_transform_|, |transform_|, and anchoring adjustments.
gfx::Transform world_space_transform_; gfx::Transform world_space_transform_;
bool world_space_transform_dirty_ = false;
UiElement* parent_ = nullptr; UiElement* parent_ = nullptr;
std::vector<std::unique_ptr<UiElement>> children_; std::vector<std::unique_ptr<UiElement>> children_;
......
...@@ -115,7 +115,7 @@ TEST(UiElement, IgnoringAsymmetricPadding) { ...@@ -115,7 +115,7 @@ TEST(UiElement, IgnoringAsymmetricPadding) {
a->AddChild(std::move(b)); a->AddChild(std::move(b));
a->DoLayOutChildren(); a->DoLayOutChildren();
a->UpdateWorldSpaceTransformRecursive(); a->UpdateWorldSpaceTransformRecursive(false);
gfx::Point3F p; gfx::Point3F p;
a->world_space_transform().TransformPoint(&p); a->world_space_transform().TransformPoint(&p);
......
...@@ -128,7 +128,8 @@ bool UiScene::OnBeginFrame(const base::TimeTicks& current_time, ...@@ -128,7 +128,8 @@ bool UiScene::OnBeginFrame(const base::TimeTicks& current_time,
// Now that we have finalized our local values, we can safely update our // Now that we have finalized our local values, we can safely update our
// final, baked transform. // final, baked transform.
root_element_->UpdateWorldSpaceTransformRecursive(); const bool parent_transform_changed = false;
root_element_->UpdateWorldSpaceTransformRecursive(parent_transform_changed);
} }
return scene_dirty; return scene_dirty;
......
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