blob: 27e2aed52cf1cbbf70a90ac454f0c260960613b0 [file] [log] [blame]
// Copyright 2014 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 "cc/surfaces/direct_compositor_frame_sink.h"
#include "base/bind.h"
#include "cc/output/compositor_frame.h"
#include "cc/output/compositor_frame_sink_client.h"
#include "cc/surfaces/display.h"
#include "cc/surfaces/frame_sink_id.h"
#include "cc/surfaces/surface.h"
#include "cc/surfaces/surface_id_allocator.h"
#include "cc/surfaces/surface_manager.h"
namespace cc {
DirectCompositorFrameSink::DirectCompositorFrameSink(
const FrameSinkId& frame_sink_id,
SurfaceManager* surface_manager,
Display* display,
scoped_refptr<ContextProvider> context_provider,
scoped_refptr<ContextProvider> worker_context_provider,
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
SharedBitmapManager* shared_bitmap_manager)
: CompositorFrameSink(std::move(context_provider),
std::move(worker_context_provider),
gpu_memory_buffer_manager,
shared_bitmap_manager),
frame_sink_id_(frame_sink_id),
surface_manager_(surface_manager),
display_(display),
factory_(frame_sink_id, surface_manager, this) {
DCHECK(thread_checker_.CalledOnValidThread());
capabilities_.can_force_reclaim_resources = true;
// Display and DirectCompositorFrameSink share a GL context, so sync
// points aren't needed when passing resources between them.
capabilities_.delegated_sync_points_required = false;
factory_.set_needs_sync_points(false);
}
DirectCompositorFrameSink::DirectCompositorFrameSink(
const FrameSinkId& frame_sink_id,
SurfaceManager* surface_manager,
Display* display,
scoped_refptr<VulkanContextProvider> vulkan_context_provider)
: CompositorFrameSink(std::move(vulkan_context_provider)),
frame_sink_id_(frame_sink_id),
surface_manager_(surface_manager),
display_(display),
factory_(frame_sink_id_, surface_manager, this) {
DCHECK(thread_checker_.CalledOnValidThread());
capabilities_.can_force_reclaim_resources = true;
}
DirectCompositorFrameSink::~DirectCompositorFrameSink() {
DCHECK(thread_checker_.CalledOnValidThread());
}
bool DirectCompositorFrameSink::BindToClient(
CompositorFrameSinkClient* client) {
DCHECK(thread_checker_.CalledOnValidThread());
if (!CompositorFrameSink::BindToClient(client))
return false;
surface_manager_->RegisterSurfaceFactoryClient(frame_sink_id_, this);
// We want the Display's output surface to hear about lost context, and since
// this shares a context with it, we should not be listening for lost context
// callbacks on the context here.
if (auto* cp = context_provider())
cp->SetLostContextCallback(base::Closure());
// Avoid initializing GL context here, as this should be sharing the
// Display's context.
display_->Initialize(this, surface_manager_);
return true;
}
void DirectCompositorFrameSink::DetachFromClient() {
// Unregister the SurfaceFactoryClient here instead of the dtor so that only
// one client is alive for this namespace at any given time.
surface_manager_->UnregisterSurfaceFactoryClient(frame_sink_id_);
if (delegated_local_frame_id_.is_valid())
factory_.Destroy(delegated_local_frame_id_);
CompositorFrameSink::DetachFromClient();
}
void DirectCompositorFrameSink::SubmitCompositorFrame(CompositorFrame frame) {
gfx::Size frame_size =
frame.delegated_frame_data->render_pass_list.back()->output_rect.size();
if (frame_size.IsEmpty() || frame_size != last_swap_frame_size_) {
if (delegated_local_frame_id_.is_valid()) {
factory_.Destroy(delegated_local_frame_id_);
}
delegated_local_frame_id_ = surface_id_allocator_.GenerateId();
factory_.Create(delegated_local_frame_id_);
last_swap_frame_size_ = frame_size;
}
display_->SetLocalFrameId(delegated_local_frame_id_,
frame.metadata.device_scale_factor);
factory_.SubmitCompositorFrame(
delegated_local_frame_id_, std::move(frame),
base::Bind(&DirectCompositorFrameSink::DidDrawCallback,
base::Unretained(this)));
}
void DirectCompositorFrameSink::ForceReclaimResources() {
if (delegated_local_frame_id_.is_valid()) {
factory_.SubmitCompositorFrame(delegated_local_frame_id_, CompositorFrame(),
SurfaceFactory::DrawCallback());
}
}
void DirectCompositorFrameSink::ReturnResources(
const ReturnedResourceArray& resources) {
if (client_)
client_->ReclaimResources(resources);
}
void DirectCompositorFrameSink::SetBeginFrameSource(
BeginFrameSource* begin_frame_source) {
DCHECK(client_);
client_->SetBeginFrameSource(begin_frame_source);
}
void DirectCompositorFrameSink::DisplayOutputSurfaceLost() {
is_lost_ = true;
client_->DidLoseCompositorFrameSink();
}
void DirectCompositorFrameSink::DisplayWillDrawAndSwap(
bool will_draw_and_swap,
const RenderPassList& render_passes) {
// This notification is not relevant to our client outside of tests.
}
void DirectCompositorFrameSink::DisplayDidDrawAndSwap() {
// This notification is not relevant to our client outside of tests. We
// unblock the client from DidDrawCallback() when the surface is going to
// be drawn.
}
void DirectCompositorFrameSink::DidDrawCallback() {
client_->DidReceiveCompositorFrameAck();
}
} // namespace cc