// Copyright 2012 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/layers/delegated_renderer_layer.h" #include "cc/layers/delegated_renderer_layer_impl.h" #include "cc/output/delegated_frame_data.h" #include "cc/quads/render_pass_draw_quad.h" #include "cc/trees/blocking_task_runner.h" #include "cc/trees/layer_tree_host.h" namespace cc { scoped_refptr DelegatedRendererLayer::Create( const scoped_refptr& frame_provider) { return scoped_refptr( new DelegatedRendererLayer(frame_provider)); } DelegatedRendererLayer::DelegatedRendererLayer( const scoped_refptr& frame_provider) : Layer(), frame_provider_(frame_provider), should_collect_new_frame_(true), frame_data_(NULL), main_thread_runner_(BlockingTaskRunner::current()), weak_ptrs_(this) { frame_provider_->AddObserver(this); } DelegatedRendererLayer::~DelegatedRendererLayer() { frame_provider_->RemoveObserver(this); } scoped_ptr DelegatedRendererLayer::CreateLayerImpl( LayerTreeImpl* tree_impl) { return DelegatedRendererLayerImpl::Create( tree_impl, layer_id_).PassAs(); } void DelegatedRendererLayer::SetLayerTreeHost(LayerTreeHost* host) { if (layer_tree_host() == host) { Layer::SetLayerTreeHost(host); return; } if (!host) { // The active frame needs to be removed from the active tree and resources // returned before the commit is called complete. // TODO(danakj): Don't need to do this if the last frame commited was empty // or we never commited a frame with resources. SetNextCommitWaitsForActivation(); } else { // There is no active frame in the new layer tree host to wait for so no // need to call SetNextCommitWaitsForActivation(). should_collect_new_frame_ = true; SetNeedsUpdate(); } Layer::SetLayerTreeHost(host); } void DelegatedRendererLayer::PushPropertiesTo(LayerImpl* impl) { Layer::PushPropertiesTo(impl); DelegatedRendererLayerImpl* delegated_impl = static_cast(impl); delegated_impl->SetDisplaySize(display_size_); delegated_impl->CreateChildIdIfNeeded( frame_provider_->GetReturnResourcesCallbackForImplThread()); if (frame_data_) delegated_impl->SetFrameData(frame_data_, frame_damage_); frame_data_ = NULL; frame_damage_ = gfx::RectF(); } void DelegatedRendererLayer::ProviderHasNewFrame() { should_collect_new_frame_ = true; SetNeedsUpdate(); // The active frame needs to be replaced and resources returned before the // commit is called complete. SetNextCommitWaitsForActivation(); } void DelegatedRendererLayer::SetDisplaySize(gfx::Size size) { if (display_size_ == size) return; display_size_ = size; SetNeedsCommit(); } static bool FrameDataRequiresFilterContext(const DelegatedFrameData* frame) { for (size_t i = 0; i < frame->render_pass_list.size(); ++i) { const QuadList& quad_list = frame->render_pass_list[i]->quad_list; for (size_t j = 0; j < quad_list.size(); ++j) { if (quad_list[j]->shared_quad_state->blend_mode != SkXfermode::kSrcOver_Mode) return true; if (quad_list[j]->material != DrawQuad::RENDER_PASS) continue; const RenderPassDrawQuad* render_pass_quad = RenderPassDrawQuad::MaterialCast(quad_list[j]); if (!render_pass_quad->filters.IsEmpty() || !render_pass_quad->background_filters.IsEmpty()) return true; } } return false; } bool DelegatedRendererLayer::Update(ResourceUpdateQueue* queue, const OcclusionTracker* occlusion) { bool updated = Layer::Update(queue, occlusion); if (!should_collect_new_frame_) return updated; frame_data_ = frame_provider_->GetFrameDataAndRefResources(this, &frame_damage_); should_collect_new_frame_ = false; // If any quad has a filter operation or a blend mode other than normal, // then we need an offscreen context to draw this layer's content. if (FrameDataRequiresFilterContext(frame_data_)) layer_tree_host()->set_needs_filter_context(); SetNeedsPushProperties(); return true; } } // namespace cc