delegated_renderer_layer.cc revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
1// Copyright 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "cc/layers/delegated_renderer_layer.h" 6 7#include "cc/layers/delegated_renderer_layer_client.h" 8#include "cc/layers/delegated_renderer_layer_impl.h" 9#include "cc/output/delegated_frame_data.h" 10#include "cc/quads/render_pass_draw_quad.h" 11#include "cc/trees/blocking_task_runner.h" 12#include "cc/trees/layer_tree_host.h" 13 14namespace cc { 15 16scoped_refptr<DelegatedRendererLayer> DelegatedRendererLayer::Create( 17 DelegatedRendererLayerClient* client) { 18 return scoped_refptr<DelegatedRendererLayer>( 19 new DelegatedRendererLayer(client)); 20} 21 22DelegatedRendererLayer::DelegatedRendererLayer( 23 DelegatedRendererLayerClient* client) 24 : Layer(), 25 client_(client), 26 needs_filter_context_(false), 27 main_thread_runner_(BlockingTaskRunner::current()), 28 weak_ptrs_(this) {} 29 30DelegatedRendererLayer::~DelegatedRendererLayer() {} 31 32scoped_ptr<LayerImpl> DelegatedRendererLayer::CreateLayerImpl( 33 LayerTreeImpl* tree_impl) { 34 return DelegatedRendererLayerImpl::Create( 35 tree_impl, layer_id_).PassAs<LayerImpl>(); 36} 37 38void DelegatedRendererLayer::SetLayerTreeHost(LayerTreeHost* host) { 39 if (layer_tree_host() == host) { 40 Layer::SetLayerTreeHost(host); 41 return; 42 } 43 44 if (!host) { 45 // The active frame needs to be removed from the active tree and resources 46 // returned before the commit is called complete. 47 // TODO(danakj): Don't need to do this if the last frame commited was empty 48 // or we never commited a frame with resources. 49 SetNextCommitWaitsForActivation(); 50 } else { 51 if (needs_filter_context_) 52 host->set_needs_filter_context(); 53 } 54 55 Layer::SetLayerTreeHost(host); 56} 57 58bool DelegatedRendererLayer::DrawsContent() const { 59 return Layer::DrawsContent() && !frame_size_.IsEmpty(); 60} 61 62void DelegatedRendererLayer::PushPropertiesTo(LayerImpl* impl) { 63 Layer::PushPropertiesTo(impl); 64 65 DelegatedRendererLayerImpl* delegated_impl = 66 static_cast<DelegatedRendererLayerImpl*>(impl); 67 68 delegated_impl->SetDisplaySize(display_size_); 69 70 delegated_impl->CreateChildIdIfNeeded( 71 base::Bind(&DelegatedRendererLayer::ReceiveUnusedResourcesOnImplThread, 72 main_thread_runner_, 73 weak_ptrs_.GetWeakPtr())); 74 75 if (frame_data_) 76 delegated_impl->SetFrameData(frame_data_.Pass(), damage_in_frame_); 77 frame_data_.reset(); 78 damage_in_frame_ = gfx::RectF(); 79 80 // The ResourceProvider will have the new frame as soon as we push it to the 81 // pending tree. So unused resources will be returned as well. 82 if (client_) 83 client_->DidCommitFrameData(); 84 85 // TODO(danakj): The DidCommitFrameData() notification requires a push 86 // properties to happen in order to notify about unused resources returned 87 // from the parent compositor. crbug.com/259090 88 needs_push_properties_ = true; 89} 90 91void DelegatedRendererLayer::SetDisplaySize(gfx::Size size) { 92 if (display_size_ == size) 93 return; 94 display_size_ = size; 95 SetNeedsCommit(); 96} 97 98void DelegatedRendererLayer::SetFrameData( 99 scoped_ptr<DelegatedFrameData> new_frame_data) { 100 DCHECK(new_frame_data); 101 102 if (frame_data_) { 103 // Copy the resources from the last provided frame into the unused resources 104 // list, as the new frame will provide its own resources. 105 TransferableResource::ReturnResources( 106 frame_data_->resource_list, 107 &unused_resources_for_child_compositor_); 108 if (client_) 109 client_->UnusedResourcesAreAvailable(); 110 } 111 frame_data_ = new_frame_data.Pass(); 112 if (!frame_data_->render_pass_list.empty()) { 113 RenderPass* root_pass = frame_data_->render_pass_list.back(); 114 damage_in_frame_.Union(root_pass->damage_rect); 115 frame_size_ = root_pass->output_rect.size(); 116 } else { 117 frame_size_ = gfx::Size(); 118 } 119 120 // If any RenderPassDrawQuad has a filter operation, then we need a filter 121 // context to draw this layer's content. 122 for (size_t i = 0; 123 !needs_filter_context_ && i < frame_data_->render_pass_list.size(); 124 ++i) { 125 const QuadList& quad_list = frame_data_->render_pass_list[i]->quad_list; 126 for (size_t j = 0; !needs_filter_context_ && j < quad_list.size(); ++j) { 127 if (quad_list[j]->material != DrawQuad::RENDER_PASS) 128 continue; 129 const RenderPassDrawQuad* render_pass_quad = 130 RenderPassDrawQuad::MaterialCast(quad_list[j]); 131 if (!render_pass_quad->filters.IsEmpty() || 132 !render_pass_quad->background_filters.IsEmpty()) 133 needs_filter_context_ = true; 134 } 135 } 136 if (needs_filter_context_ && layer_tree_host()) 137 layer_tree_host()->set_needs_filter_context(); 138 139 SetNeedsCommit(); 140 // The active frame needs to be replaced and resources returned before the 141 // commit is called complete. 142 SetNextCommitWaitsForActivation(); 143} 144 145void DelegatedRendererLayer::TakeUnusedResourcesForChildCompositor( 146 ReturnedResourceArray* array) { 147 DCHECK(array->empty()); 148 array->clear(); 149 150 array->swap(unused_resources_for_child_compositor_); 151} 152 153void DelegatedRendererLayer::ReceiveUnusedResources( 154 const ReturnedResourceArray& unused) { 155 unused_resources_for_child_compositor_.insert( 156 unused_resources_for_child_compositor_.end(), 157 unused.begin(), 158 unused.end()); 159 if (client_) 160 client_->UnusedResourcesAreAvailable(); 161} 162 163// static 164void DelegatedRendererLayer::ReceiveUnusedResourcesOnImplThread( 165 scoped_refptr<BlockingTaskRunner> task_runner, 166 base::WeakPtr<DelegatedRendererLayer> self, 167 const ReturnedResourceArray& unused) { 168 task_runner->PostTask( 169 FROM_HERE, 170 base::Bind( 171 &DelegatedRendererLayer::ReceiveUnusedResources, self, unused)); 172} 173 174} // namespace cc 175