| // Copyright 2015 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 "services/ui/ws/server_window_compositor_frame_sink_manager.h" |
| |
| #include "mojo/public/cpp/bindings/strong_binding.h" |
| #include "services/ui/surfaces/display_compositor.h" |
| #include "services/ui/surfaces/gpu_compositor_frame_sink.h" |
| #include "services/ui/ws/ids.h" |
| #include "services/ui/ws/server_window.h" |
| #include "services/ui/ws/server_window_delegate.h" |
| |
| namespace ui { |
| namespace ws { |
| |
| ServerWindowCompositorFrameSinkManager::ServerWindowCompositorFrameSinkManager( |
| ServerWindow* window) |
| : window_(window), |
| waiting_for_initial_frames_( |
| window_->properties().count(ui::mojom::kWaitForUnderlay_Property) > |
| 0) {} |
| |
| ServerWindowCompositorFrameSinkManager:: |
| ~ServerWindowCompositorFrameSinkManager() { |
| } |
| |
| bool ServerWindowCompositorFrameSinkManager::ShouldDraw() { |
| if (!waiting_for_initial_frames_) |
| return true; |
| |
| waiting_for_initial_frames_ = !IsCompositorFrameSinkReadyAndNonEmpty( |
| mojom::CompositorFrameSinkType::DEFAULT) || |
| !IsCompositorFrameSinkReadyAndNonEmpty( |
| mojom::CompositorFrameSinkType::UNDERLAY); |
| return !waiting_for_initial_frames_; |
| } |
| |
| void ServerWindowCompositorFrameSinkManager::CreateCompositorFrameSink( |
| mojom::CompositorFrameSinkType compositor_frame_sink_type, |
| gfx::AcceleratedWidget widget, |
| cc::mojom::MojoCompositorFrameSinkRequest request, |
| cc::mojom::MojoCompositorFrameSinkClientPtr client) { |
| cc::FrameSinkId frame_sink_id( |
| WindowIdToTransportId(window_->id()), |
| static_cast<uint32_t>(compositor_frame_sink_type)); |
| CompositorFrameSinkData& data = |
| type_to_compositor_frame_sink_map_[compositor_frame_sink_type]; |
| cc::mojom::MojoCompositorFrameSinkPrivateRequest private_request; |
| if (data.pending_compositor_frame_sink_request.is_pending()) { |
| private_request = std::move(data.pending_compositor_frame_sink_request); |
| } else { |
| private_request = mojo::GetProxy(&data.compositor_frame_sink); |
| } |
| |
| // TODO(fsamuel): AcceleratedWidget cannot be transported over IPC for Mac or |
| // Android. We should instead use GpuSurfaceTracker here on those platforms. |
| window_->delegate()->GetDisplayCompositor()->CreateCompositorFrameSink( |
| frame_sink_id, widget, std::move(request), std::move(private_request), |
| std::move(client)); |
| |
| if (window_->parent()) { |
| window_->delegate() |
| ->GetRootWindow(window_) |
| ->GetOrCreateCompositorFrameSinkManager() |
| ->AddChildFrameSinkId(mojom::CompositorFrameSinkType::DEFAULT, |
| frame_sink_id); |
| } |
| } |
| |
| void ServerWindowCompositorFrameSinkManager::AddChildFrameSinkId( |
| mojom::CompositorFrameSinkType compositor_frame_sink_type, |
| const cc::FrameSinkId& frame_sink_id) { |
| auto it = type_to_compositor_frame_sink_map_.find(compositor_frame_sink_type); |
| if (it != type_to_compositor_frame_sink_map_.end()) { |
| it->second.compositor_frame_sink->AddChildFrameSink(frame_sink_id); |
| return; |
| } |
| CompositorFrameSinkData& data = |
| type_to_compositor_frame_sink_map_[compositor_frame_sink_type]; |
| data.pending_compositor_frame_sink_request = |
| mojo::GetProxy(&data.compositor_frame_sink); |
| data.compositor_frame_sink->AddChildFrameSink(frame_sink_id); |
| } |
| |
| void ServerWindowCompositorFrameSinkManager::RemoveChildFrameSinkId( |
| mojom::CompositorFrameSinkType compositor_frame_sink_type, |
| const cc::FrameSinkId& frame_sink_id) { |
| auto it = type_to_compositor_frame_sink_map_.find(compositor_frame_sink_type); |
| DCHECK(it != type_to_compositor_frame_sink_map_.end()); |
| it->second.compositor_frame_sink->AddChildFrameSink(frame_sink_id); |
| } |
| |
| bool ServerWindowCompositorFrameSinkManager::HasCompositorFrameSinkOfType( |
| mojom::CompositorFrameSinkType type) const { |
| return type_to_compositor_frame_sink_map_.count(type) > 0; |
| } |
| |
| bool ServerWindowCompositorFrameSinkManager::HasAnyCompositorFrameSink() const { |
| return HasCompositorFrameSinkOfType( |
| mojom::CompositorFrameSinkType::DEFAULT) || |
| HasCompositorFrameSinkOfType(mojom::CompositorFrameSinkType::UNDERLAY); |
| } |
| |
| gfx::Size ServerWindowCompositorFrameSinkManager::GetLatestFrameSize( |
| mojom::CompositorFrameSinkType type) const { |
| auto it = type_to_compositor_frame_sink_map_.find(type); |
| if (it == type_to_compositor_frame_sink_map_.end()) |
| return gfx::Size(); |
| |
| return it->second.latest_submitted_frame_size; |
| } |
| |
| cc::SurfaceId ServerWindowCompositorFrameSinkManager::GetLatestSurfaceId( |
| mojom::CompositorFrameSinkType type) const { |
| auto it = type_to_compositor_frame_sink_map_.find(type); |
| if (it == type_to_compositor_frame_sink_map_.end()) |
| return cc::SurfaceId(); |
| |
| return it->second.latest_submitted_surface_id; |
| } |
| |
| void ServerWindowCompositorFrameSinkManager::SetLatestSurfaceInfo( |
| mojom::CompositorFrameSinkType type, |
| const cc::SurfaceId& surface_id, |
| const gfx::Size& frame_size) { |
| CompositorFrameSinkData& data = type_to_compositor_frame_sink_map_[type]; |
| data.latest_submitted_surface_id = surface_id; |
| data.latest_submitted_frame_size = frame_size; |
| } |
| |
| bool ServerWindowCompositorFrameSinkManager:: |
| IsCompositorFrameSinkReadyAndNonEmpty( |
| mojom::CompositorFrameSinkType type) const { |
| auto iter = type_to_compositor_frame_sink_map_.find(type); |
| if (iter == type_to_compositor_frame_sink_map_.end()) |
| return false; |
| if (iter->second.latest_submitted_frame_size.IsEmpty()) |
| return false; |
| const gfx::Size& latest_submitted_frame_size = |
| iter->second.latest_submitted_frame_size; |
| return latest_submitted_frame_size.width() >= window_->bounds().width() && |
| latest_submitted_frame_size.height() >= window_->bounds().height(); |
| } |
| |
| CompositorFrameSinkData::CompositorFrameSinkData() {} |
| |
| CompositorFrameSinkData::~CompositorFrameSinkData() {} |
| |
| CompositorFrameSinkData::CompositorFrameSinkData( |
| CompositorFrameSinkData&& other) |
| : latest_submitted_surface_id(other.latest_submitted_surface_id), |
| compositor_frame_sink(std::move(other.compositor_frame_sink)) {} |
| |
| CompositorFrameSinkData& CompositorFrameSinkData::operator=( |
| CompositorFrameSinkData&& other) { |
| latest_submitted_surface_id = other.latest_submitted_surface_id; |
| compositor_frame_sink = std::move(other.compositor_frame_sink); |
| return *this; |
| } |
| |
| } // namespace ws |
| } // namespace ui |