blob: fbf05bc9b21e3fbcff19d0c00fdb8cf3a2924372 [file] [log] [blame]
// Copyright 2018 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.
#ifndef CONTENT_BROWSER_ANDROID_SYNCHRONOUS_COMPOSITOR_SYNC_CALL_BRIDGE_H_
#define CONTENT_BROWSER_ANDROID_SYNCHRONOUS_COMPOSITOR_SYNC_CALL_BRIDGE_H_
#include "base/containers/circular_deque.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/thread_annotations.h"
#include "components/viz/common/quads/compositor_frame.h"
#include "content/common/input/sync_compositor_messages.h"
#include "content/public/browser/android/synchronous_compositor.h"
namespace content {
class SynchronousCompositorHost;
// For the synchronous compositor feature of webview it is necessary
// that the UI thread to block until the renderer process has processed
// certain messages entirely. (beginframe and resulting compositor frames).
// This object is used to manage the waiting and signaling behavior on the UI
// thread. The UI thread will wait on a WaitableEvent (via FrameFuture class)
// or condition variable which is then signal by handlers in this class.
// This object is a cross thread object accessed both on the UI and IO threads.
//
// Examples of call graphs are:
// Browser UI Thread Browser IO Thread Renderer
//
// ->VSync Java
// ----------------------------------------------->BeginFrame
// CV Wait
// BeginFrameRes<----------
// CVSignal
// WakeUp
//
//
// ->DrawHwAsync
// RegisterFrameFuture
// ----------------------------------------------->DrawHwAsync
// Do some stuff
// FrameFuture::GetFrame()
// WaitableEvent::Wait()
// ReceiveFrame<---------------
// WaitableEvent::Signal()
// WakeUp
//
// This may seem simple but it gets a little more complicated when
// multiple views are involved. Each view will have it's own SyncCallBridge.
//
// Once example is:
//
// Browser UI Thread Browser IO Thread Renderer1 Renderer2
//
// ->VSync Java
// ----------------------------------------------->BeginFrame
// BeginFrameRes<----------
// CVSignal
// ------------------------------------------------------------>BeginFrame
// CV Wait
// BeginFrameRes<----------------------------
// CVSignal
// WakeUp
//
// Notice that it is possible that before we wait on a CV variable a renderer
// may have already responded to the BeginFrame request.
//
class SynchronousCompositorSyncCallBridge
: public base::RefCountedThreadSafe<SynchronousCompositorSyncCallBridge> {
public:
explicit SynchronousCompositorSyncCallBridge(SynchronousCompositorHost* host);
// Indicatation that the remote is now ready to process requests. Called
// on either UI or IO thread.
void RemoteReady();
// Remote channel is closed signal all waiters.
void RemoteClosedOnIOThread();
// Receive a frame. Return false if the corresponding frame wasn't found.
bool ReceiveFrameOnIOThread(int frame_sink_id,
uint32_t metadata_version,
base::Optional<viz::CompositorFrame>);
// Receive a BeginFrameResponse. Returns true if handling the response was
// successful or not.
bool BeginFrameResponseOnIOThread(
const SyncCompositorCommonRendererParams& render_params);
// Schedule a callback for when vsync finishes and wait for the
// BeginFrameResponse callback.
bool WaitAfterVSyncOnUIThread(ui::WindowAndroid* window_android);
// Store a FrameFuture for a later ReceiveFrame callback. Return if the
// future was stored for further handling.
bool SetFrameFutureOnUIThread(
scoped_refptr<SynchronousCompositor::FrameFuture> frame_future);
// Indicate the host is destroyed.
void HostDestroyedOnUIThread();
// Return whether the remote side is ready.
bool IsRemoteReadyOnUIThread();
private:
friend class base::RefCountedThreadSafe<SynchronousCompositorSyncCallBridge>;
~SynchronousCompositorSyncCallBridge();
// Callback passed to WindowAndroid, runs when the current begin frame is
// completed.
void BeginFrameCompleteOnUIThread();
// Process metadata.
void ProcessFrameMetadataOnUIThread(uint32_t metadata_version,
viz::CompositorFrameMetadata metadata);
// Signal all waiters for closure. Callee must host a lock to |lock_|.
void SignalRemoteClosedToAllWaitersOnIOThread()
EXCLUSIVE_LOCKS_REQUIRED(lock_);
using FrameFutureQueue =
base::circular_deque<scoped_refptr<SynchronousCompositor::FrameFuture>>;
enum class RemoteState { INIT, READY, CLOSED };
const int routing_id_;
// UI thread only.
SynchronousCompositorHost* host_;
// Shared variables between the IO thread and UI thread.
base::Lock lock_;
FrameFutureQueue frame_futures_ GUARDED_BY(lock_);
bool begin_frame_response_valid_ GUARDED_BY(lock_) = false;
SyncCompositorCommonRendererParams last_render_params_ GUARDED_BY(lock_);
base::ConditionVariable begin_frame_condition_ GUARDED_BY(lock_);
RemoteState remote_state_ GUARDED_BY(lock_) = RemoteState::INIT;
DISALLOW_COPY_AND_ASSIGN(SynchronousCompositorSyncCallBridge);
};
} // namespace content
#endif // CONTENT_BROWSER_ANDROID_SYNCHRONOUS_COMPOSITOR_SYNC_CALL_BRIDGE_H_