blob: cdebf905c36c288372ced91a9d8dc5bdf87ab6ef [file] [log] [blame]
// Copyright 2019 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 <vector>
#include "base/containers/circular_deque.h"
#include "base/sequence_checker.h"
#include "cc/trees/layer_tree_host.h"
namespace cc {
// Maintains a queue of callbacks and compositor frame times that we want to
// buffer until a relevant frame is presented.
// Callbacks are queued through |RegisterMainThreadPresentationCallbacks|.
// Once a frame is presented, users of this class can call
// |PopPendingCallbacks| to get their callbacks back. This class never runs
// callbacks itself so it's up to calling code to |PostTask| as needed.
// This class is thread unsafe so concurrent access would require external
// synchronization. In practice, however, instances of this class are only used
// on the compositor thread even though the buffered callbacks are intended to
// be run on the renderer main thread.
// CC_EXPORT is only needed for testing.
class CC_EXPORT PresentationTimeCallbackBuffer {
using CallbackType = LayerTreeHost::PresentationTimeCallback;
PresentationTimeCallbackBuffer(const PresentationTimeCallbackBuffer&) =
PresentationTimeCallbackBuffer& operator=(
const PresentationTimeCallbackBuffer&) = delete;
PresentationTimeCallbackBuffer& operator=(PresentationTimeCallbackBuffer&&);
// Buffers the given |callbacks| in preparation for a GPU frame swap at or
// after the given |frame_token|. Calling code posts these callbacks to the
// main thread once they're popped.
void RegisterMainThreadPresentationCallbacks(
uint32_t frame_token,
std::vector<CallbackType> callbacks);
// The given |frame_time| is associated with the given |frame_token| and will
// be exposed through |PopPendingCallbacks| if there is an exact frame token
// match. Note that it is an error to register distinct |frame_time|s against
// the same |frame_token|.
void RegisterFrameTime(uint32_t frame_token, base::TimeTicks frame_time);
// Structured return value for |PopPendingCallbacks|. CC_EXPORT is only
// needed for testing.
struct CC_EXPORT PendingCallbacks {
PendingCallbacks(const PendingCallbacks&) = delete;
PendingCallbacks& operator=(const PendingCallbacks&) = delete;
PendingCallbacks& operator=(PendingCallbacks&&);
// Holds callbacks registered through
// |RegisterMainThreadPresentationCallbacks|.
std::vector<CallbackType> main_thread_callbacks;
// Note: calling code needs to test against frame_time.is_null() because
// frame_time is not always defined. See |PopPendingCallbacks|.
base::TimeTicks frame_time;
// Call this once the presentation for the given |frame_token| has completed.
// Yields any pending callbacks that were registered against a frame token
// that was less than or equal to the given |frame_token|. It is the caller's
// responsibility to run the callbacks on the right threads/sequences. When
// the given |frame_token| is an exact match to a registered entry,
// |frame_time| will be set to the frame time supplied through
// |RegisterFrameTime|. Otherwise, |frame_time| will be default constructed
// and should not be used. Calling code can assume |frame_time| is meaningful
// iff frame_time.is_null() returns false.
PendingCallbacks PopPendingCallbacks(uint32_t frame_token);
// Stores information needed once we get a response for a particular
// presentation token.
struct FrameTokenInfo {
explicit FrameTokenInfo(uint32_t token);
FrameTokenInfo(const FrameTokenInfo&) = delete;
FrameTokenInfo& operator=(const FrameTokenInfo&) = delete;
FrameTokenInfo& operator=(FrameTokenInfo&&);
// A |CompositorFrameMetadata::frame_token| that we use to associate
// presentation feedback with the relevant compositor frame.
uint32_t token;
// A copy of the |frame_time| from the |BeginFrameArgs| associated with
// frame. Useful for tracking latency between frame requests and frame
// presentations.
base::TimeTicks frame_time;
// The callbacks to send back to the main thread.
std::vector<CallbackType> main_thread_callbacks;
// Returns a reference to a |FrameTokenInfo| with the given |frame_token|.
// The instance is created if necessary and occupies the appropriate place in
// |frame_token_infos_|.
FrameTokenInfo& GetOrMakeRegistration(uint32_t frame_token);
// Queue of pending registrations ordered by |token|. We can use a deque
// because we require callers to use non-decreasing tokens when registering.
base::circular_deque<FrameTokenInfo> frame_token_infos_;
// When DCHECK is enabled, check that instances of this class aren't being
// used concurrently.
} // namespace cc