| 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 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 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_(false), |
| 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 // Become the observer for the frame provider. This can be stolen by another |
| 34 // DelegatedRendererLayer and then we will stop getting new frames. |
| 35 frame_provider_->SetObserver(this); |
| 36 } |
| 29 | 37 |
| 30 DelegatedRendererLayer::~DelegatedRendererLayer() {} | 38 DelegatedRendererLayer::~DelegatedRendererLayer() { |
| 39 if (frame_provider_->IsObserver(this)) |
| 40 frame_provider_->SetObserver(NULL); |
| 41 } |
| 31 | 42 |
| 32 scoped_ptr<LayerImpl> DelegatedRendererLayer::CreateLayerImpl( | 43 scoped_ptr<LayerImpl> DelegatedRendererLayer::CreateLayerImpl( |
| 33 LayerTreeImpl* tree_impl) { | 44 LayerTreeImpl* tree_impl) { |
| 34 return DelegatedRendererLayerImpl::Create( | 45 return DelegatedRendererLayerImpl::Create( |
| 35 tree_impl, layer_id_).PassAs<LayerImpl>(); | 46 tree_impl, layer_id_).PassAs<LayerImpl>(); |
| 36 } | 47 } |
| 37 | 48 |
| 38 void DelegatedRendererLayer::SetLayerTreeHost(LayerTreeHost* host) { | 49 void DelegatedRendererLayer::SetLayerTreeHost(LayerTreeHost* host) { |
| 39 if (layer_tree_host() == host) { | 50 if (layer_tree_host() == host) { |
| 40 Layer::SetLayerTreeHost(host); | 51 Layer::SetLayerTreeHost(host); |
| 41 return; | 52 return; |
| 42 } | 53 } |
| 43 | 54 |
| 44 if (!host) { | 55 if (!host) { |
| 45 // The active frame needs to be removed from the active tree and resources | 56 // The active frame needs to be removed from the active tree and resources |
| 46 // returned before the commit is called complete. | 57 // returned before the commit is called complete. |
| 47 // TODO(danakj): Don't need to do this if the last frame commited was empty | 58 // TODO(danakj): Don't need to do this if the last frame commited was empty |
| 48 // or we never commited a frame with resources. | 59 // or we never commited a frame with resources. |
| 49 SetNextCommitWaitsForActivation(); | 60 SetNextCommitWaitsForActivation(); |
| 50 } else { | 61 } else { |
| 51 if (needs_filter_context_) | 62 // There is no active frame in the new layer tree host to wait for so no |
| 52 host->set_needs_filter_context(); | 63 // need to call SetNextCommitWaitsForActivation(). |
| 64 should_collect_new_frame_ = true; |
| 65 SetNeedsUpdate(); |
| 53 } | 66 } |
| 54 | 67 |
| 55 Layer::SetLayerTreeHost(host); | 68 Layer::SetLayerTreeHost(host); |
| 56 } | 69 } |
| 57 | 70 |
| 58 bool DelegatedRendererLayer::DrawsContent() const { | |
| 59 return Layer::DrawsContent() && !frame_size_.IsEmpty(); | |
| 60 } | |
| 61 | |
| 62 void DelegatedRendererLayer::PushPropertiesTo(LayerImpl* impl) { | 71 void DelegatedRendererLayer::PushPropertiesTo(LayerImpl* impl) { |
| 63 Layer::PushPropertiesTo(impl); | 72 Layer::PushPropertiesTo(impl); |
| 64 | 73 |
| 65 DelegatedRendererLayerImpl* delegated_impl = | 74 DelegatedRendererLayerImpl* delegated_impl = |
| 66 static_cast<DelegatedRendererLayerImpl*>(impl); | 75 static_cast<DelegatedRendererLayerImpl*>(impl); |
| 67 | 76 |
| 68 delegated_impl->SetDisplaySize(display_size_); | 77 delegated_impl->SetDisplaySize(display_size_); |
| 69 | 78 |
| 70 delegated_impl->CreateChildIdIfNeeded( | 79 delegated_impl->CreateChildIdIfNeeded( |
| 71 base::Bind(&DelegatedRendererLayer::ReceiveUnusedResourcesOnImplThread, | 80 frame_provider_->GetReturnResourcesCallbackForImplThread()); |
| 72 main_thread_runner_, | |
| 73 weak_ptrs_.GetWeakPtr())); | |
| 74 | 81 |
| 75 if (frame_data_) | 82 if (frame_data_) |
| 76 delegated_impl->SetFrameData(frame_data_.Pass(), damage_in_frame_); | 83 delegated_impl->SetFrameData(frame_data_, frame_damage_); |
| 77 frame_data_.reset(); | 84 frame_data_ = NULL; |
| 78 damage_in_frame_ = gfx::RectF(); | 85 frame_damage_ = gfx::RectF(); |
| 79 | 86 |
| 80 // The ResourceProvider will have the new frame as soon as we push it to the | 87 // 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. | 88 // pending tree. So resources no longer in use will be returned as well. |
| 82 if (client_) | 89 if (client_) |
| 83 client_->DidCommitFrameData(); | 90 client_->DidCommitFrameData(); |
| 84 | 91 |
| 85 // TODO(danakj): The DidCommitFrameData() notification requires a push | 92 // TODO(danakj): The DidCommitFrameData() notification requires a push |
| 86 // properties to happen in order to notify about unused resources returned | 93 // properties to happen in order to notify about resources returned |
| 87 // from the parent compositor. crbug.com/259090 | 94 // from the parent compositor that are no longer in use. crbug.com/259090 |
| 88 needs_push_properties_ = true; | 95 needs_push_properties_ = true; |
| 89 } | 96 } |
| 90 | 97 |
| 98 void DelegatedRendererLayer::ProviderHasNewFrame() { |
| 99 should_collect_new_frame_ = true; |
| 100 SetNeedsUpdate(); |
| 101 // The active frame needs to be replaced and resources returned before the |
| 102 // commit is called complete. |
| 103 SetNextCommitWaitsForActivation(); |
| 104 } |
| 105 |
| 91 void DelegatedRendererLayer::SetDisplaySize(gfx::Size size) { | 106 void DelegatedRendererLayer::SetDisplaySize(gfx::Size size) { |
| 92 if (display_size_ == size) | 107 if (display_size_ == size) |
| 93 return; | 108 return; |
| 94 display_size_ = size; | 109 display_size_ = size; |
| 95 SetNeedsCommit(); | 110 SetNeedsCommit(); |
| 96 } | 111 } |
| 97 | 112 |
| 98 void DelegatedRendererLayer::SetFrameData( | 113 static bool FrameDataHasFilter(DelegatedFrameData* frame) { |
| 99 scoped_ptr<DelegatedFrameData> new_frame_data) { | 114 for (size_t i = 0; i < frame->render_pass_list.size(); ++i) { |
| 100 DCHECK(new_frame_data); | 115 const QuadList& quad_list = frame->render_pass_list[i]->quad_list; |
| 101 | 116 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) | 117 if (quad_list[j]->material != DrawQuad::RENDER_PASS) |
| 128 continue; | 118 continue; |
| 129 const RenderPassDrawQuad* render_pass_quad = | 119 const RenderPassDrawQuad* render_pass_quad = |
| 130 RenderPassDrawQuad::MaterialCast(quad_list[j]); | 120 RenderPassDrawQuad::MaterialCast(quad_list[j]); |
| 131 if (!render_pass_quad->filters.IsEmpty() || | 121 if (!render_pass_quad->filters.IsEmpty() || |
| 132 !render_pass_quad->background_filters.IsEmpty()) | 122 !render_pass_quad->background_filters.IsEmpty()) |
| 133 needs_filter_context_ = true; | 123 return true; |
| 134 } | 124 } |
| 135 } | 125 } |
| 136 if (needs_filter_context_ && layer_tree_host()) | 126 return false; |
| 127 } |
| 128 |
| 129 bool DelegatedRendererLayer::Update(ResourceUpdateQueue* queue, |
| 130 const OcclusionTracker* occlusion) { |
| 131 bool updated = Layer::Update(queue, occlusion); |
| 132 if (!should_collect_new_frame_) |
| 133 return updated; |
| 134 |
| 135 frame_data_ = |
| 136 frame_provider_->GetFrameDataAndRefResources(this, &frame_damage_); |
| 137 should_collect_new_frame_ = false; |
| 138 |
| 139 // If any quad has a filter operation, then we need a filter context to draw |
| 140 // this layer's content. |
| 141 if (FrameDataHasFilter(frame_data_) && layer_tree_host()) |
| 137 layer_tree_host()->set_needs_filter_context(); | 142 layer_tree_host()->set_needs_filter_context(); |
| 138 | 143 |
| 139 SetNeedsCommit(); | 144 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 } | 145 } |
| 173 | 146 |
| 174 } // namespace cc | 147 } // namespace cc |
| OLD | NEW |