blob: 74727ec1375ed7f3c7be6b5d4c3549223ae59f5b [file] [log] [blame]
// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cobalt/browser/render_tree_combiner.h"
#include <map>
#include "base/memory/scoped_ptr.h"
#include "base/optional.h"
#include "base/time.h"
#include "cobalt/render_tree/composition_node.h"
#include "cobalt/render_tree/rect_node.h"
#include "cobalt/renderer/renderer_module.h"
#include "cobalt/renderer/submission.h"
namespace cobalt {
namespace browser {
RenderTreeCombiner::Layer::Layer(RenderTreeCombiner* render_tree_combiner)
: render_tree_combiner_(render_tree_combiner),
render_tree_(base::nullopt),
receipt_time_(base::nullopt) {}
RenderTreeCombiner::Layer::~Layer() {
DCHECK(render_tree_combiner_);
render_tree_combiner_->RemoveLayer(this);
render_tree_combiner_->SubmitToRenderer();
}
void RenderTreeCombiner::Layer::Submit(
const base::optional<renderer::Submission>& render_tree_submission,
bool receive_time) {
render_tree_ = render_tree_submission;
if (receive_time) {
receipt_time_ = base::TimeTicks::HighResNow();
} else {
receipt_time_ = base::nullopt;
}
DCHECK(render_tree_combiner_);
render_tree_combiner_->SubmitToRenderer();
}
RenderTreeCombiner::RenderTreeCombiner(
renderer::RendererModule* renderer_module, const math::Size& viewport_size)
: renderer_module_(renderer_module), viewport_size_(viewport_size) {}
scoped_ptr<RenderTreeCombiner::Layer> RenderTreeCombiner::CreateLayer(
int z_index) {
if (layers_.count(z_index) > 0) {
return scoped_ptr<RenderTreeCombiner::Layer>(NULL);
}
RenderTreeCombiner::Layer* layer = new Layer(this);
layers_[z_index] = layer;
return scoped_ptr<RenderTreeCombiner::Layer>(layers_[z_index]);
}
void RenderTreeCombiner::RemoveLayer(const Layer* layer) {
for (auto it = layers_.begin(); it != layers_.end(); /* no increment */) {
if (it->second == layer) {
it = layers_.erase(it);
} else {
++it;
}
}
}
void RenderTreeCombiner::SubmitToRenderer() {
render_tree::CompositionNode::Builder builder;
// Add children for all layers in order.
base::optional<renderer::Submission> first_tree = base::nullopt;
base::optional<renderer::Submission> combined_submission = base::nullopt;
for (auto it = layers_.begin(); it != layers_.end(); ++it) {
RenderTreeCombiner::Layer* layer = it->second;
if (layer->render_tree_) {
builder.AddChild(layer->render_tree_->render_tree);
first_tree = layer->render_tree_;
// Make the combined submission with the first receipt_time_ we find.
if (!combined_submission && layer->receipt_time_) {
combined_submission = renderer::Submission(*layer->render_tree_);
combined_submission->time_offset =
layer->render_tree_->time_offset +
(base::TimeTicks::HighResNow() - *layer->receipt_time_);
}
}
}
if (!first_tree) {
return;
}
if (!combined_submission) {
// None of the layers store the time.
combined_submission = renderer::Submission(*first_tree);
}
combined_submission->render_tree = new render_tree::CompositionNode(builder);
renderer_module_->pipeline()->Submit(*combined_submission);
}
} // namespace browser
} // namespace cobalt