Commit c37cd75b authored by boliu's avatar boliu Committed by Commit bot

sync compositor: Signal async frame on IO thread

Continuation of CL by ojars@ here:
https://codereview.chromium.org/2383933002/

Async hardware draw synchronously returns a frame future that is
fulfilled asynchronously on the IO thread. This allows the frame future
to be waited on either the UI thread or android's render thread without
deadlocks.

In content, make SynchronousCompositorObserver a true message
filter owned by RenderProcessHostImpl. Will rename this to SCFilter
in a later CL.

In android_webview, wait on the frame future in kModeDraw,
immediately before where the frame is needed, to maximize
parallelization.

Note that there is a hack in BVR to produce a synchronous frame
first to ensure that bindings are initialized before render thread runs
any code.

This makes a complete more or less working path. But there are still
lots of TODOs needs to be fixed before the async path is ready to
ship.

BUG=636164

Review-Url: https://codereview.chromium.org/2418383002
Cr-Commit-Position: refs/heads/master@{#427096}
parent 75b542fe
...@@ -109,7 +109,8 @@ BrowserViewRenderer::BrowserViewRenderer( ...@@ -109,7 +109,8 @@ BrowserViewRenderer::BrowserViewRenderer(
max_page_scale_factor_(0.f), max_page_scale_factor_(0.f),
on_new_picture_enable_(false), on_new_picture_enable_(false),
clear_view_(false), clear_view_(false),
offscreen_pre_raster_(false) {} offscreen_pre_raster_(false),
allow_async_draw_(false) {}
BrowserViewRenderer::~BrowserViewRenderer() { BrowserViewRenderer::~BrowserViewRenderer() {
DCHECK(compositor_map_.empty()); DCHECK(compositor_map_.empty());
...@@ -232,20 +233,24 @@ bool BrowserViewRenderer::OnDrawHardware() { ...@@ -232,20 +233,24 @@ bool BrowserViewRenderer::OnDrawHardware() {
gfx::Rect viewport_rect_for_tile_priority = gfx::Rect viewport_rect_for_tile_priority =
ComputeViewportRectForTilePriority(); ComputeViewportRectForTilePriority();
if (async_on_draw_hardware_) { scoped_refptr<content::SynchronousCompositor::FrameFuture> future; // Async.
compositor_->DemandDrawHwAsync(size_, viewport_rect_for_tile_priority, content::SynchronousCompositor::Frame frame; // Sync.
transform_for_tile_priority); bool async = async_on_draw_hardware_ && allow_async_draw_;
return current_compositor_frame_consumer_->HasFrameOnUI(); if (async) {
future = compositor_->DemandDrawHwAsync(
size_, viewport_rect_for_tile_priority, transform_for_tile_priority);
} else {
frame = compositor_->DemandDrawHw(size_, viewport_rect_for_tile_priority,
transform_for_tile_priority);
} }
content::SynchronousCompositor::Frame frame = compositor_->DemandDrawHw( if (!frame.frame && !future) {
size_, viewport_rect_for_tile_priority, transform_for_tile_priority);
if (!frame.frame) {
TRACE_EVENT_INSTANT0("android_webview", "NoNewFrame", TRACE_EVENT_INSTANT0("android_webview", "NoNewFrame",
TRACE_EVENT_SCOPE_THREAD); TRACE_EVENT_SCOPE_THREAD);
return current_compositor_frame_consumer_->HasFrameOnUI(); return current_compositor_frame_consumer_->HasFrameOnUI();
} }
allow_async_draw_ = true;
std::unique_ptr<ChildFrame> child_frame = base::MakeUnique<ChildFrame>( std::unique_ptr<ChildFrame> child_frame = base::MakeUnique<ChildFrame>(
frame.compositor_frame_sink_id, std::move(frame.frame), compositor_id_, frame.compositor_frame_sink_id, std::move(frame.frame), compositor_id_,
viewport_rect_for_tile_priority.IsEmpty(), transform_for_tile_priority, viewport_rect_for_tile_priority.IsEmpty(), transform_for_tile_priority,
...@@ -254,29 +259,10 @@ bool BrowserViewRenderer::OnDrawHardware() { ...@@ -254,29 +259,10 @@ bool BrowserViewRenderer::OnDrawHardware() {
ReturnUnusedResource( ReturnUnusedResource(
current_compositor_frame_consumer_->PassUncommittedFrameOnUI()); current_compositor_frame_consumer_->PassUncommittedFrameOnUI());
current_compositor_frame_consumer_->SetFrameOnUI(std::move(child_frame), current_compositor_frame_consumer_->SetFrameOnUI(std::move(child_frame),
nullptr); std::move(future));
return true; return true;
} }
void BrowserViewRenderer::OnDrawHardwareProcessFrameFuture(
const scoped_refptr<content::SynchronousCompositor::FrameFuture>&
frame_future) {
gfx::Transform transform_for_tile_priority =
external_draw_constraints_.transform;
gfx::Rect viewport_rect_for_tile_priority =
ComputeViewportRectForTilePriority();
ReturnUnusedResource(
current_compositor_frame_consumer_->PassUncommittedFrameOnUI());
current_compositor_frame_consumer_->SetFrameOnUI(
base::MakeUnique<ChildFrame>(
0, nullptr, compositor_id_, viewport_rect_for_tile_priority.IsEmpty(),
transform_for_tile_priority, offscreen_pre_raster_,
external_draw_constraints_.is_layer),
frame_future);
}
gfx::Rect BrowserViewRenderer::ComputeViewportRectForTilePriority() { gfx::Rect BrowserViewRenderer::ComputeViewportRectForTilePriority() {
// If the WebView is on a layer, WebView does not know what transform is // If the WebView is on a layer, WebView does not know what transform is
// applied onto the layer so global visible rect does not make sense here. // applied onto the layer so global visible rect does not make sense here.
......
...@@ -130,9 +130,6 @@ class BrowserViewRenderer : public content::SynchronousCompositorClient, ...@@ -130,9 +130,6 @@ class BrowserViewRenderer : public content::SynchronousCompositorClient,
const gfx::Vector2dF& latest_overscroll_delta, const gfx::Vector2dF& latest_overscroll_delta,
const gfx::Vector2dF& current_fling_velocity) override; const gfx::Vector2dF& current_fling_velocity) override;
ui::TouchHandleDrawable* CreateDrawable() override; ui::TouchHandleDrawable* CreateDrawable() override;
void OnDrawHardwareProcessFrameFuture(
const scoped_refptr<content::SynchronousCompositor::FrameFuture>&
frame_future) override;
// CompositorFrameProducer overrides // CompositorFrameProducer overrides
void OnParentDrawConstraintsUpdated( void OnParentDrawConstraintsUpdated(
...@@ -204,6 +201,10 @@ class BrowserViewRenderer : public content::SynchronousCompositorClient, ...@@ -204,6 +201,10 @@ class BrowserViewRenderer : public content::SynchronousCompositorClient,
bool offscreen_pre_raster_; bool offscreen_pre_raster_;
// Must do a synchronous draw first to ensure GL bindings are initialized.
// TODO(boliu): Wait on render thread and remove this.
bool allow_async_draw_;
gfx::Vector2d last_on_draw_scroll_offset_; gfx::Vector2d last_on_draw_scroll_offset_;
gfx::Rect last_on_draw_global_visible_rect_; gfx::Rect last_on_draw_global_visible_rect_;
......
...@@ -30,7 +30,8 @@ class ChildFrame { ...@@ -30,7 +30,8 @@ class ChildFrame {
bool is_layer); bool is_layer);
~ChildFrame(); ~ChildFrame();
const uint32_t compositor_frame_sink_id; // These two fields are not const to make async path easier.
uint32_t compositor_frame_sink_id;
std::unique_ptr<cc::CompositorFrame> frame; std::unique_ptr<cc::CompositorFrame> frame;
// The id of the compositor this |frame| comes from. // The id of the compositor this |frame| comes from.
const CompositorID compositor_id; const CompositorID compositor_id;
......
...@@ -61,17 +61,35 @@ void HardwareRenderer::CommitFrame() { ...@@ -61,17 +61,35 @@ void HardwareRenderer::CommitFrame() {
render_thread_manager_->PassFrameOnRT(); render_thread_manager_->PassFrameOnRT();
if (!child_frame.get()) if (!child_frame.get())
return; return;
last_committed_compositor_frame_sink_id_ =
child_frame->compositor_frame_sink_id;
ReturnResourcesInChildFrame(); ReturnResourcesInChildFrame();
frame_future_ = render_thread_manager_->PassFrameFutureOnRT();
child_frame_ = std::move(child_frame); child_frame_ = std::move(child_frame);
DCHECK(child_frame_->frame.get());
} }
void HardwareRenderer::DrawGL(AwDrawGLInfo* draw_info) { void HardwareRenderer::DrawGL(AwDrawGLInfo* draw_info) {
TRACE_EVENT0("android_webview", "HardwareRenderer::DrawGL"); TRACE_EVENT0("android_webview", "HardwareRenderer::DrawGL");
if (frame_future_) {
TRACE_EVENT0("android_webview", "GetFrame");
DCHECK(child_frame_);
DCHECK(!child_frame_->frame);
std::unique_ptr<content::SynchronousCompositor::Frame> frame =
frame_future_->getFrame();
if (frame) {
child_frame_->compositor_frame_sink_id = frame->compositor_frame_sink_id;
child_frame_->frame = std::move(frame->frame);
} else {
child_frame_.reset();
}
frame_future_ = nullptr;
}
if (child_frame_) {
last_committed_compositor_frame_sink_id_ =
child_frame_->compositor_frame_sink_id;
}
// We need to watch if the current Android context has changed and enforce // We need to watch if the current Android context has changed and enforce
// a clean-up in the compositor. // a clean-up in the compositor.
EGLContext current_context = eglGetCurrentContext(); EGLContext current_context = eglGetCurrentContext();
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "cc/surfaces/frame_sink_id.h" #include "cc/surfaces/frame_sink_id.h"
#include "cc/surfaces/surface_factory_client.h" #include "cc/surfaces/surface_factory_client.h"
#include "cc/surfaces/surface_id.h" #include "cc/surfaces/surface_id.h"
#include "content/public/browser/android/synchronous_compositor.h"
struct AwDrawGLInfo; struct AwDrawGLInfo;
...@@ -66,6 +67,8 @@ class HardwareRenderer : public cc::SurfaceFactoryClient { ...@@ -66,6 +67,8 @@ class HardwareRenderer : public cc::SurfaceFactoryClient {
// SurfaceFactory. // SurfaceFactory.
std::unique_ptr<ChildFrame> child_frame_; std::unique_ptr<ChildFrame> child_frame_;
scoped_refptr<content::SynchronousCompositor::FrameFuture> frame_future_;
const scoped_refptr<SurfacesInstance> surfaces_; const scoped_refptr<SurfacesInstance> surfaces_;
cc::FrameSinkId frame_sink_id_; cc::FrameSinkId frame_sink_id_;
const std::unique_ptr<cc::SurfaceIdAllocator> surface_id_allocator_; const std::unique_ptr<cc::SurfaceIdAllocator> surface_id_allocator_;
......
...@@ -193,6 +193,8 @@ void RenderThreadManager::SetFrameOnUI( ...@@ -193,6 +193,8 @@ void RenderThreadManager::SetFrameOnUI(
std::unique_ptr<ChildFrame> RenderThreadManager::GetSynchronousCompositorFrame( std::unique_ptr<ChildFrame> RenderThreadManager::GetSynchronousCompositorFrame(
scoped_refptr<content::SynchronousCompositor::FrameFuture> frame_future, scoped_refptr<content::SynchronousCompositor::FrameFuture> frame_future,
std::unique_ptr<ChildFrame> child_frame) { std::unique_ptr<ChildFrame> child_frame) {
if (!frame_future)
return nullptr;
DCHECK(!child_frame->frame.get()); DCHECK(!child_frame->frame.get());
std::unique_ptr<content::SynchronousCompositor::Frame> frame = std::unique_ptr<content::SynchronousCompositor::Frame> frame =
frame_future->getFrame(); frame_future->getFrame();
...@@ -210,13 +212,15 @@ std::unique_ptr<ChildFrame> RenderThreadManager::PassFrameOnRT() { ...@@ -210,13 +212,15 @@ std::unique_ptr<ChildFrame> RenderThreadManager::PassFrameOnRT() {
base::AutoLock lock(lock_); base::AutoLock lock(lock_);
hardware_renderer_has_frame_ = hardware_renderer_has_frame_ =
hardware_renderer_has_frame_ || child_frame_.get(); hardware_renderer_has_frame_ || child_frame_.get();
if (async_on_draw_hardware_ && child_frame_.get()) {
return GetSynchronousCompositorFrame(std::move(frame_future_),
std::move(child_frame_));
}
return std::move(child_frame_); return std::move(child_frame_);
} }
scoped_refptr<content::SynchronousCompositor::FrameFuture>
RenderThreadManager::PassFrameFutureOnRT() {
base::AutoLock lock(lock_);
return std::move(frame_future_);
}
std::unique_ptr<ChildFrame> RenderThreadManager::PassUncommittedFrameOnUI() { std::unique_ptr<ChildFrame> RenderThreadManager::PassUncommittedFrameOnUI() {
base::AutoLock lock(lock_); base::AutoLock lock(lock_);
if (async_on_draw_hardware_ && child_frame_.get()) { if (async_on_draw_hardware_ && child_frame_.get()) {
......
...@@ -60,9 +60,11 @@ class RenderThreadManager : public CompositorFrameConsumer { ...@@ -60,9 +60,11 @@ class RenderThreadManager : public CompositorFrameConsumer {
bool HasFrameOnUI() const override; bool HasFrameOnUI() const override;
void DeleteHardwareRendererOnUI() override; void DeleteHardwareRendererOnUI() override;
// RT thread methods. // Render thread methods.
gfx::Vector2d GetScrollOffsetOnRT(); gfx::Vector2d GetScrollOffsetOnRT();
std::unique_ptr<ChildFrame> PassFrameOnRT(); std::unique_ptr<ChildFrame> PassFrameOnRT();
scoped_refptr<content::SynchronousCompositor::FrameFuture>
PassFrameFutureOnRT();
void DrawGL(AwDrawGLInfo* draw_info); void DrawGL(AwDrawGLInfo* draw_info);
void PostExternalDrawConstraintsToChildCompositorOnRT( void PostExternalDrawConstraintsToChildCompositorOnRT(
const ParentCompositorDrawConstraints& parent_draw_constraints); const ParentCompositorDrawConstraints& parent_draw_constraints);
......
...@@ -70,7 +70,6 @@ SynchronousCompositorHost::SynchronousCompositorHost( ...@@ -70,7 +70,6 @@ SynchronousCompositorHost::SynchronousCompositorHost(
ui_task_runner_(BrowserThread::GetTaskRunnerForThread(BrowserThread::UI)), ui_task_runner_(BrowserThread::GetTaskRunnerForThread(BrowserThread::UI)),
process_id_(rwhva_->GetRenderWidgetHost()->GetProcess()->GetID()), process_id_(rwhva_->GetRenderWidgetHost()->GetProcess()->GetID()),
routing_id_(rwhva_->GetRenderWidgetHost()->GetRoutingID()), routing_id_(rwhva_->GetRenderWidgetHost()->GetRoutingID()),
rph_observer_(SynchronousCompositorObserver::GetOrCreateFor(process_id_)),
sender_(rwhva_->GetRenderWidgetHost()), sender_(rwhva_->GetRenderWidgetHost()),
use_in_process_zero_copy_software_draw_(use_in_proc_software_draw), use_in_process_zero_copy_software_draw_(use_in_proc_software_draw),
bytes_limit_(0u), bytes_limit_(0u),
...@@ -91,21 +90,27 @@ bool SynchronousCompositorHost::OnMessageReceived(const IPC::Message& message) { ...@@ -91,21 +90,27 @@ bool SynchronousCompositorHost::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(SyncCompositorHostMsg_CompositorFrameSinkCreated, IPC_MESSAGE_HANDLER(SyncCompositorHostMsg_CompositorFrameSinkCreated,
CompositorFrameSinkCreated) CompositorFrameSinkCreated)
IPC_MESSAGE_HANDLER(SyncCompositorHostMsg_UpdateState, ProcessCommonParams) IPC_MESSAGE_HANDLER(SyncCompositorHostMsg_UpdateState, ProcessCommonParams)
IPC_MESSAGE_HANDLER_GENERIC(SyncCompositorHostMsg_ReturnFrame,
DemandDrawHwReceiveFrame(message))
IPC_MESSAGE_UNHANDLED(handled = false) IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP() IPC_END_MESSAGE_MAP()
return handled; return handled;
} }
void SynchronousCompositorHost::DemandDrawHwAsync( scoped_refptr<SynchronousCompositor::FrameFuture>
SynchronousCompositorHost::DemandDrawHwAsync(
const gfx::Size& viewport_size, const gfx::Size& viewport_size,
const gfx::Rect& viewport_rect_for_tile_priority, const gfx::Rect& viewport_rect_for_tile_priority,
const gfx::Transform& transform_for_tile_priority) { const gfx::Transform& transform_for_tile_priority) {
SyncCompositorDemandDrawHwParams params(viewport_size, SyncCompositorDemandDrawHwParams params(viewport_size,
viewport_rect_for_tile_priority, viewport_rect_for_tile_priority,
transform_for_tile_priority); transform_for_tile_priority);
sender_->Send(new SyncCompositorMsg_DemandDrawHwAsync(routing_id_, params)); scoped_refptr<FrameFuture> frame_future = new FrameFuture();
if (SynchronousCompositorObserver* filter = GetFilter()) {
filter->SetFrameFuture(routing_id_, frame_future);
sender_->Send(new SyncCompositorMsg_DemandDrawHwAsync(routing_id_, params));
} else {
frame_future->setFrame(nullptr);
}
return frame_future;
} }
SynchronousCompositor::Frame SynchronousCompositorHost::DemandDrawHw( SynchronousCompositor::Frame SynchronousCompositorHost::DemandDrawHw(
...@@ -131,28 +136,6 @@ SynchronousCompositor::Frame SynchronousCompositorHost::DemandDrawHw( ...@@ -131,28 +136,6 @@ SynchronousCompositor::Frame SynchronousCompositorHost::DemandDrawHw(
std::move(compositor_frame)); std::move(compositor_frame));
} }
bool SynchronousCompositorHost::DemandDrawHwReceiveFrame(
const IPC::Message& message) {
SyncCompositorHostMsg_ReturnFrame::Param param;
if (!SyncCompositorHostMsg_ReturnFrame::Read(&message, &param))
return false;
uint32_t compositor_frame_sink_id = std::get<0>(param);
cc::CompositorFrame compositor_frame = std::move(std::get<1>(param));
scoped_refptr<SynchronousCompositor::FrameFuture> frame_future =
new FrameFuture();
SynchronousCompositor::Frame frame = ProcessHardwareFrame(
compositor_frame_sink_id, std::move(compositor_frame));
if (!frame.frame)
return true;
std::unique_ptr<SynchronousCompositor::Frame> frame_ptr =
base::MakeUnique<SynchronousCompositor::Frame>();
frame_ptr->frame = std::move(frame.frame);
frame_ptr->compositor_frame_sink_id = frame.compositor_frame_sink_id;
frame_future->setFrame(std::move(frame_ptr));
client_->OnDrawHardwareProcessFrameFuture(std::move(frame_future));
return true;
}
SynchronousCompositor::Frame SynchronousCompositorHost::ProcessHardwareFrame( SynchronousCompositor::Frame SynchronousCompositorHost::ProcessHardwareFrame(
uint32_t compositor_frame_sink_id, uint32_t compositor_frame_sink_id,
cc::CompositorFrame compositor_frame) { cc::CompositorFrame compositor_frame) {
...@@ -175,6 +158,12 @@ void SynchronousCompositorHost::UpdateFrameMetaData( ...@@ -175,6 +158,12 @@ void SynchronousCompositorHost::UpdateFrameMetaData(
rwhva_->SynchronousFrameMetadata(std::move(frame_metadata)); rwhva_->SynchronousFrameMetadata(std::move(frame_metadata));
} }
SynchronousCompositorObserver* SynchronousCompositorHost::GetFilter() {
return static_cast<RenderProcessHostImpl*>(
rwhva_->GetRenderWidgetHost()->GetProcess())
->synchronous_compositor_filter();
}
namespace { namespace {
class ScopedSetSkCanvas { class ScopedSetSkCanvas {
...@@ -387,7 +376,8 @@ void SynchronousCompositorHost::DidOverscroll( ...@@ -387,7 +376,8 @@ void SynchronousCompositorHost::DidOverscroll(
void SynchronousCompositorHost::DidSendBeginFrame( void SynchronousCompositorHost::DidSendBeginFrame(
ui::WindowAndroid* window_android) { ui::WindowAndroid* window_android) {
rph_observer_->SyncStateAfterVSync(window_android, this); if (SynchronousCompositorObserver* filter = GetFilter())
filter->SyncStateAfterVSync(window_android, this);
} }
void SynchronousCompositorHost::CompositorFrameSinkCreated() { void SynchronousCompositorHost::CompositorFrameSinkCreated() {
......
...@@ -59,7 +59,7 @@ class SynchronousCompositorHost : public SynchronousCompositor { ...@@ -59,7 +59,7 @@ class SynchronousCompositorHost : public SynchronousCompositor {
const gfx::Size& viewport_size, const gfx::Size& viewport_size,
const gfx::Rect& viewport_rect_for_tile_priority, const gfx::Rect& viewport_rect_for_tile_priority,
const gfx::Transform& transform_for_tile_priority) override; const gfx::Transform& transform_for_tile_priority) override;
void DemandDrawHwAsync( scoped_refptr<FrameFuture> DemandDrawHwAsync(
const gfx::Size& viewport_size, const gfx::Size& viewport_size,
const gfx::Rect& viewport_rect_for_tile_priority, const gfx::Rect& viewport_rect_for_tile_priority,
const gfx::Transform& transform_for_tile_priority) override; const gfx::Transform& transform_for_tile_priority) override;
...@@ -99,14 +99,13 @@ class SynchronousCompositorHost : public SynchronousCompositor { ...@@ -99,14 +99,13 @@ class SynchronousCompositorHost : public SynchronousCompositor {
SynchronousCompositor::Frame ProcessHardwareFrame( SynchronousCompositor::Frame ProcessHardwareFrame(
uint32_t compositor_frame_sink_id, uint32_t compositor_frame_sink_id,
cc::CompositorFrame compositor_frame); cc::CompositorFrame compositor_frame);
bool DemandDrawHwReceiveFrame(const IPC::Message& message); SynchronousCompositorObserver* GetFilter();
RenderWidgetHostViewAndroid* const rwhva_; RenderWidgetHostViewAndroid* const rwhva_;
SynchronousCompositorClient* const client_; SynchronousCompositorClient* const client_;
const scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; const scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
const int process_id_; const int process_id_;
const int routing_id_; const int routing_id_;
SynchronousCompositorObserver* const rph_observer_;
IPC::Sender* const sender_; IPC::Sender* const sender_;
const bool use_in_process_zero_copy_software_draw_; const bool use_in_process_zero_copy_software_draw_;
......
...@@ -16,40 +16,16 @@ ...@@ -16,40 +16,16 @@
namespace content { namespace content {
namespace {
base::LazyInstance<std::map<int, SynchronousCompositorObserver*>> g_instances;
}
// static
SynchronousCompositorObserver* SynchronousCompositorObserver::GetOrCreateFor(
int process_id) {
auto itr = g_instances.Get().find(process_id);
if (itr != g_instances.Get().end())
return itr->second;
return new SynchronousCompositorObserver(process_id);
}
SynchronousCompositorObserver::SynchronousCompositorObserver(int process_id) SynchronousCompositorObserver::SynchronousCompositorObserver(int process_id)
: render_process_host_(RenderProcessHost::FromID(process_id)), : BrowserMessageFilter(SyncCompositorMsgStart),
render_process_host_(RenderProcessHost::FromID(process_id)),
window_android_in_vsync_(nullptr) { window_android_in_vsync_(nullptr) {
DCHECK(render_process_host_); DCHECK(render_process_host_);
DCHECK(!base::ContainsKey(g_instances.Get(), render_process_host_->GetID()));
g_instances.Get()[render_process_host_->GetID()] = this;
render_process_host_->AddObserver(this);
} }
SynchronousCompositorObserver::~SynchronousCompositorObserver() { SynchronousCompositorObserver::~SynchronousCompositorObserver() {
DCHECK(compositor_host_pending_renderer_state_.empty()); DCHECK(compositor_host_pending_renderer_state_.empty());
DCHECK(base::ContainsKey(g_instances.Get(), render_process_host_->GetID())); // TODO(boliu): signal pending frames.
DCHECK_EQ(this, g_instances.Get()[render_process_host_->GetID()]);
render_process_host_->RemoveObserver(this);
g_instances.Get().erase(render_process_host_->GetID());
}
void SynchronousCompositorObserver::RenderProcessHostDestroyed(
RenderProcessHost* host) {
DCHECK_EQ(render_process_host_, host);
delete this;
} }
void SynchronousCompositorObserver::SyncStateAfterVSync( void SynchronousCompositorObserver::SyncStateAfterVSync(
...@@ -68,6 +44,58 @@ void SynchronousCompositorObserver::SyncStateAfterVSync( ...@@ -68,6 +44,58 @@ void SynchronousCompositorObserver::SyncStateAfterVSync(
window_android_in_vsync_->AddObserver(this); window_android_in_vsync_->AddObserver(this);
} }
bool SynchronousCompositorObserver::OnMessageReceived(
const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(SynchronousCompositorObserver, message)
IPC_MESSAGE_HANDLER_GENERIC(SyncCompositorHostMsg_ReturnFrame,
ReceiveFrame(message))
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
bool SynchronousCompositorObserver::ReceiveFrame(const IPC::Message& message) {
SyncCompositorHostMsg_ReturnFrame::Param param;
if (!SyncCompositorHostMsg_ReturnFrame::Read(&message, &param))
return false;
int routing_id = message.routing_id();
scoped_refptr<SynchronousCompositor::FrameFuture> future;
{
base::AutoLock lock(future_map_lock_);
auto itr = future_map_.find(routing_id);
if (itr == future_map_.end()) {
bad_message::ReceivedBadMessage(render_process_host_,
bad_message::SCO_INVALID_ARGUMENT);
return true;
}
future = std::move(itr->second);
DCHECK(future);
future_map_.erase(itr);
}
auto frame_ptr = base::MakeUnique<SynchronousCompositor::Frame>();
frame_ptr->compositor_frame_sink_id = std::get<0>(param);
cc::CompositorFrame& compositor_frame = std::get<1>(param);
if (compositor_frame.delegated_frame_data) {
frame_ptr->frame.reset(new cc::CompositorFrame);
*frame_ptr->frame = std::move(compositor_frame);
}
future->setFrame(std::move(frame_ptr));
// TODO(boliu): Post metadata back to UI thread.
return true;
}
void SynchronousCompositorObserver::SetFrameFuture(
int routing_id,
scoped_refptr<SynchronousCompositor::FrameFuture> frame_future) {
// TODO(boliu): Need a sequenced id, to queue previous frames.
DCHECK(frame_future);
base::AutoLock lock(future_map_lock_);
future_map_[routing_id] = std::move(frame_future);
}
void SynchronousCompositorObserver::OnCompositingDidCommit() { void SynchronousCompositorObserver::OnCompositingDidCommit() {
NOTREACHED(); NOTREACHED();
} }
......
...@@ -8,7 +8,9 @@ ...@@ -8,7 +8,9 @@
#include <vector> #include <vector>
#include "base/macros.h" #include "base/macros.h"
#include "content/public/browser/render_process_host_observer.h" #include "base/synchronization/lock.h"
#include "content/public/browser/android/synchronous_compositor.h"
#include "content/public/browser/browser_message_filter.h"
#include "ui/android/window_android_observer.h" #include "ui/android/window_android_observer.h"
namespace ui { namespace ui {
...@@ -17,17 +19,14 @@ class WindowAndroid; ...@@ -17,17 +19,14 @@ class WindowAndroid;
namespace content { namespace content {
class RenderProcessHost;
class SynchronousCompositorHost; class SynchronousCompositorHost;
// SynchronousCompositor class that's tied to the lifetime of a // TODO(boliu): Rename this to SynchronousCompositorFilter.
// RenderProcessHost. Responsible for its own lifetime. class SynchronousCompositorObserver : public ui::WindowAndroidObserver,
class SynchronousCompositorObserver : public RenderProcessHostObserver, public BrowserMessageFilter {
public ui::WindowAndroidObserver {
public: public:
static SynchronousCompositorObserver* GetOrCreateFor(int process_id); explicit SynchronousCompositorObserver(int process_id);
// RenderProcessHostObserver overrides.
void RenderProcessHostDestroyed(RenderProcessHost* host) override;
// WindowAndroidObserver overrides. // WindowAndroidObserver overrides.
void OnCompositingDidCommit() override; void OnCompositingDidCommit() override;
...@@ -39,13 +38,20 @@ class SynchronousCompositorObserver : public RenderProcessHostObserver, ...@@ -39,13 +38,20 @@ class SynchronousCompositorObserver : public RenderProcessHostObserver,
void OnActivityStopped() override; void OnActivityStopped() override;
void OnActivityStarted() override; void OnActivityStarted() override;
// BrowserMessageFilter overrides.
bool OnMessageReceived(const IPC::Message& message) override;
void SyncStateAfterVSync(ui::WindowAndroid* window_android, void SyncStateAfterVSync(ui::WindowAndroid* window_android,
SynchronousCompositorHost* compositor_host); SynchronousCompositorHost* compositor_host);
void SetFrameFuture(
int routing_id,
scoped_refptr<SynchronousCompositor::FrameFuture> frame_future);
private: private:
explicit SynchronousCompositorObserver(int process_id);
~SynchronousCompositorObserver() override; ~SynchronousCompositorObserver() override;
bool ReceiveFrame(const IPC::Message& message);
RenderProcessHost* const render_process_host_; RenderProcessHost* const render_process_host_;
// For synchronizing renderer state after a vsync. // For synchronizing renderer state after a vsync.
...@@ -53,6 +59,11 @@ class SynchronousCompositorObserver : public RenderProcessHostObserver, ...@@ -53,6 +59,11 @@ class SynchronousCompositorObserver : public RenderProcessHostObserver,
std::vector<SynchronousCompositorHost*> std::vector<SynchronousCompositorHost*>
compositor_host_pending_renderer_state_; compositor_host_pending_renderer_state_;
base::Lock future_map_lock_; // Protects |future_map_|.
using FrameFutureMap =
std::map<int, scoped_refptr<SynchronousCompositor::FrameFuture>>;
FrameFutureMap future_map_;
DISALLOW_COPY_AND_ASSIGN(SynchronousCompositorObserver); DISALLOW_COPY_AND_ASSIGN(SynchronousCompositorObserver);
}; };
......
...@@ -1203,6 +1203,8 @@ void RenderProcessHostImpl::CreateMessageFilters() { ...@@ -1203,6 +1203,8 @@ void RenderProcessHostImpl::CreateMessageFilters() {
GetID(), storage_partition_impl_->GetServiceWorkerContext())); GetID(), storage_partition_impl_->GetServiceWorkerContext()));
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
AddFilter(new ScreenOrientationMessageFilterAndroid()); AddFilter(new ScreenOrientationMessageFilterAndroid());
synchronous_compositor_filter_ = new SynchronousCompositorObserver(GetID());
AddFilter(synchronous_compositor_filter_.get());
#endif #endif
} }
......
...@@ -39,6 +39,10 @@ ...@@ -39,6 +39,10 @@
#include "ui/gfx/gpu_memory_buffer.h" #include "ui/gfx/gpu_memory_buffer.h"
#include "ui/gl/gpu_switching_observer.h" #include "ui/gl/gpu_switching_observer.h"
#if defined(OS_ANDROID)
#include "content/browser/android/synchronous_compositor_observer.h"
#endif
namespace base { namespace base {
class CommandLine; class CommandLine;
class MessageLoop; class MessageLoop;
...@@ -262,6 +266,12 @@ class CONTENT_EXPORT RenderProcessHostImpl ...@@ -262,6 +266,12 @@ class CONTENT_EXPORT RenderProcessHostImpl
return notification_message_filter_.get(); return notification_message_filter_.get();
} }
#if defined(OS_ANDROID)
SynchronousCompositorObserver* synchronous_compositor_filter() const {
return synchronous_compositor_filter_.get();
}
#endif
void set_is_for_guests_only_for_testing(bool is_for_guests_only) { void set_is_for_guests_only_for_testing(bool is_for_guests_only) {
is_for_guests_only_ = is_for_guests_only; is_for_guests_only_ = is_for_guests_only;
} }
...@@ -461,6 +471,10 @@ class CONTENT_EXPORT RenderProcessHostImpl ...@@ -461,6 +471,10 @@ class CONTENT_EXPORT RenderProcessHostImpl
// closure per notification that must be freed when the notification closes. // closure per notification that must be freed when the notification closes.
scoped_refptr<NotificationMessageFilter> notification_message_filter_; scoped_refptr<NotificationMessageFilter> notification_message_filter_;
#if defined(OS_ANDROID)
scoped_refptr<SynchronousCompositorObserver> synchronous_compositor_filter_;
#endif
// Used in single-process mode. // Used in single-process mode.
std::unique_ptr<base::Thread> in_process_renderer_; std::unique_ptr<base::Thread> in_process_renderer_;
......
...@@ -86,10 +86,8 @@ class CONTENT_EXPORT SynchronousCompositor { ...@@ -86,10 +86,8 @@ class CONTENT_EXPORT SynchronousCompositor {
const gfx::Rect& viewport_rect_for_tile_priority, const gfx::Rect& viewport_rect_for_tile_priority,
const gfx::Transform& transform_for_tile_priority) = 0; const gfx::Transform& transform_for_tile_priority) = 0;
// Same as DemandDrawHw, but uses asynchronous IPC messages. Calls // Same as DemandDrawHw, but uses asynchronous IPC messages.
// SynchronousCompositorClient::OnDrawHardwareProcessFrame to return the virtual scoped_refptr<FrameFuture> DemandDrawHwAsync(
// frame.
virtual void DemandDrawHwAsync(
const gfx::Size& viewport_size, const gfx::Size& viewport_size,
const gfx::Rect& viewport_rect_for_tile_priority, const gfx::Rect& viewport_rect_for_tile_priority,
const gfx::Transform& transform_for_tile_priority) = 0; const gfx::Transform& transform_for_tile_priority) = 0;
......
...@@ -56,10 +56,6 @@ class SynchronousCompositorClient { ...@@ -56,10 +56,6 @@ class SynchronousCompositorClient {
virtual ui::TouchHandleDrawable* CreateDrawable() = 0; virtual ui::TouchHandleDrawable* CreateDrawable() = 0;
virtual void OnDrawHardwareProcessFrameFuture(
const scoped_refptr<content::SynchronousCompositor::FrameFuture>&
frame_future) = 0;
protected: protected:
SynchronousCompositorClient() {} SynchronousCompositorClient() {}
virtual ~SynchronousCompositorClient() {} virtual ~SynchronousCompositorClient() {}
......
...@@ -33,10 +33,13 @@ SynchronousCompositor::Frame TestSynchronousCompositor::DemandDrawHw( ...@@ -33,10 +33,13 @@ SynchronousCompositor::Frame TestSynchronousCompositor::DemandDrawHw(
return std::move(hardware_frame_); return std::move(hardware_frame_);
} }
void TestSynchronousCompositor::DemandDrawHwAsync( scoped_refptr<SynchronousCompositor::FrameFuture>
TestSynchronousCompositor::DemandDrawHwAsync(
const gfx::Size& viewport_size, const gfx::Size& viewport_size,
const gfx::Rect& viewport_rect_for_tile_priority, const gfx::Rect& viewport_rect_for_tile_priority,
const gfx::Transform& transform_for_tile_priority) {} const gfx::Transform& transform_for_tile_priority) {
return nullptr;
}
void TestSynchronousCompositor::ReturnResources( void TestSynchronousCompositor::ReturnResources(
uint32_t compositor_frame_sink_id, uint32_t compositor_frame_sink_id,
......
...@@ -28,7 +28,7 @@ class CONTENT_EXPORT TestSynchronousCompositor : public SynchronousCompositor { ...@@ -28,7 +28,7 @@ class CONTENT_EXPORT TestSynchronousCompositor : public SynchronousCompositor {
const gfx::Size& viewport_size, const gfx::Size& viewport_size,
const gfx::Rect& viewport_rect_for_tile_priority, const gfx::Rect& viewport_rect_for_tile_priority,
const gfx::Transform& transform_for_tile_priority) override; const gfx::Transform& transform_for_tile_priority) override;
void DemandDrawHwAsync( scoped_refptr<FrameFuture> DemandDrawHwAsync(
const gfx::Size& viewport_size, const gfx::Size& viewport_size,
const gfx::Rect& viewport_rect_for_tile_priority, const gfx::Rect& viewport_rect_for_tile_priority,
const gfx::Transform& transform_for_tile_priority) override; const gfx::Transform& transform_for_tile_priority) override;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment