blob: 1af8594ce41b414fdcfd94a021be80544a96ed77 [file] [log] [blame]
// Copyright (c) 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 "content/renderer/gpu/renderer_compositor_frame_sink.h"
#include <utility>
#include "base/command_line.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "cc/output/compositor_frame.h"
#include "cc/output/compositor_frame_sink_client.h"
#include "cc/output/managed_memory_policy.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "content/common/view_messages.h"
#include "content/public/common/content_switches.h"
#include "content/renderer/gpu/frame_swap_message_queue.h"
#include "content/renderer/render_thread_impl.h"
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/ipc/client/command_buffer_proxy_impl.h"
#include "ipc/ipc_sync_channel.h"
namespace content {
RendererCompositorFrameSink::RendererCompositorFrameSink(
int32_t routing_id,
uint32_t compositor_frame_sink_id,
std::unique_ptr<cc::BeginFrameSource> begin_frame_source,
scoped_refptr<cc::ContextProvider> context_provider,
scoped_refptr<cc::ContextProvider> worker_context_provider,
scoped_refptr<FrameSwapMessageQueue> swap_frame_message_queue)
: CompositorFrameSink(std::move(context_provider),
std::move(worker_context_provider)),
compositor_frame_sink_id_(compositor_frame_sink_id),
compositor_frame_sink_filter_(
RenderThreadImpl::current()->compositor_message_filter()),
message_sender_(RenderThreadImpl::current()->sync_message_filter()),
frame_swap_message_queue_(swap_frame_message_queue),
begin_frame_source_(std::move(begin_frame_source)),
routing_id_(routing_id) {
DCHECK(compositor_frame_sink_filter_);
DCHECK(frame_swap_message_queue_);
DCHECK(message_sender_);
DCHECK(begin_frame_source_);
}
RendererCompositorFrameSink::RendererCompositorFrameSink(
int32_t routing_id,
uint32_t compositor_frame_sink_id,
std::unique_ptr<cc::BeginFrameSource> begin_frame_source,
scoped_refptr<cc::VulkanContextProvider> vulkan_context_provider,
scoped_refptr<FrameSwapMessageQueue> swap_frame_message_queue)
: CompositorFrameSink(std::move(vulkan_context_provider)),
compositor_frame_sink_id_(compositor_frame_sink_id),
compositor_frame_sink_filter_(
RenderThreadImpl::current()->compositor_message_filter()),
message_sender_(RenderThreadImpl::current()->sync_message_filter()),
frame_swap_message_queue_(swap_frame_message_queue),
begin_frame_source_(std::move(begin_frame_source)),
routing_id_(routing_id) {
DCHECK(compositor_frame_sink_filter_);
DCHECK(frame_swap_message_queue_);
DCHECK(message_sender_);
DCHECK(begin_frame_source_);
}
RendererCompositorFrameSink::~RendererCompositorFrameSink() = default;
bool RendererCompositorFrameSink::BindToClient(
cc::CompositorFrameSinkClient* client) {
if (!cc::CompositorFrameSink::BindToClient(client))
return false;
DCHECK(begin_frame_source_);
client_->SetBeginFrameSource(begin_frame_source_.get());
compositor_frame_sink_proxy_ = new RendererCompositorFrameSinkProxy(this);
compositor_frame_sink_filter_handler_ =
base::Bind(&RendererCompositorFrameSinkProxy::OnMessageReceived,
compositor_frame_sink_proxy_);
compositor_frame_sink_filter_->AddHandlerOnCompositorThread(
routing_id_, compositor_frame_sink_filter_handler_);
return true;
}
void RendererCompositorFrameSink::DetachFromClient() {
if (!HasClient())
return;
client_->SetBeginFrameSource(nullptr);
// Destroy the begin frame source on the same thread it was bound on.
// The CompositorFrameSink itself is destroyed on the main thread.
begin_frame_source_ = nullptr;
if (compositor_frame_sink_proxy_) {
compositor_frame_sink_proxy_->ClearCompositorFrameSink();
compositor_frame_sink_filter_->RemoveHandlerOnCompositorThread(
routing_id_, compositor_frame_sink_filter_handler_);
}
cc::CompositorFrameSink::DetachFromClient();
}
void RendererCompositorFrameSink::SwapBuffers(cc::CompositorFrame frame) {
{
std::unique_ptr<FrameSwapMessageQueue::SendMessageScope>
send_message_scope =
frame_swap_message_queue_->AcquireSendMessageScope();
std::vector<std::unique_ptr<IPC::Message>> messages;
std::vector<IPC::Message> messages_to_deliver_with_frame;
frame_swap_message_queue_->DrainMessages(&messages);
FrameSwapMessageQueue::TransferMessages(&messages,
&messages_to_deliver_with_frame);
Send(new ViewHostMsg_SwapCompositorFrame(routing_id_,
compositor_frame_sink_id_, frame,
messages_to_deliver_with_frame));
// ~send_message_scope.
}
}
void RendererCompositorFrameSink::OnMessageReceived(
const IPC::Message& message) {
DCHECK(client_thread_checker_.CalledOnValidThread());
if (!HasClient())
return;
IPC_BEGIN_MESSAGE_MAP(RendererCompositorFrameSink, message)
IPC_MESSAGE_HANDLER(ViewMsg_ReclaimCompositorResources,
OnReclaimCompositorResources);
IPC_END_MESSAGE_MAP()
}
void RendererCompositorFrameSink::OnReclaimCompositorResources(
uint32_t compositor_frame_sink_id,
bool is_swap_ack,
const cc::ReturnedResourceArray& resources) {
// Ignore message if it's a stale one coming from a different output surface
// (e.g. after a lost context).
if (compositor_frame_sink_id != compositor_frame_sink_id_)
return;
client_->ReclaimResources(resources);
if (is_swap_ack)
client_->DidSwapBuffersComplete();
}
bool RendererCompositorFrameSink::Send(IPC::Message* message) {
return message_sender_->Send(message);
}
} // namespace content