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