#ifndef ASH_FRAME_SINK_FRAME_SINK_HOLDER_H_
#define ASH_FRAME_SINK_FRAME_SINK_HOLDER_H_
#include <cstdint>
#include <memory>
#include <vector>
#include "ash/ash_export.h"
#include "ash/frame_sink/frame_sink_host.h"
#include "ash/frame_sink/ui_resource_manager.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/scoped_observation.h"
#include "cc/scheduler/scheduler.h"
#include "cc/trees/layer_tree_frame_sink_client.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "components/viz/common/quads/compositor_frame.h"
#include "ui/aura/window_observer.h"
namespace cc {
class LayerTreeFrameSink;
}
namespace ash {
class FrameSinkHolderTestApi;
class ASH_EXPORT FrameSinkHolder final : public cc::LayerTreeFrameSinkClient,
public viz::BeginFrameObserverBase,
public aura::WindowObserver {
public:
using PresentationCallback =
base::RepeatingCallback<void(const gfx::PresentationFeedback&)>;
using GetCompositorFrameCallback =
base::RepeatingCallback<std::unique_ptr<viz::CompositorFrame>(
const viz::BeginFrameAck& begin_frame_ack,
UiResourceManager& resource_manager,
bool auto_update,
const gfx::Size& last_submitted_frame_size,
float last_submitted_frame_dsf)>;
using OnFirstFrameRequestedCallback = base::OnceCallback<void()>;
using OnFrameSinkLost = base::OnceCallback<void()>;
FrameSinkHolder(
std::unique_ptr<cc::LayerTreeFrameSink> frame_sink,
GetCompositorFrameCallback get_compositor_frame_callback,
OnFirstFrameRequestedCallback on_first_frame_requested_callback,
OnFrameSinkLost on_frame_sink_lost_callback);
FrameSinkHolder(const FrameSinkHolder&) = delete;
FrameSinkHolder& operator=(const FrameSinkHolder&) = delete;
~FrameSinkHolder() override;
static bool DeleteWhenLastResourceHasBeenReclaimed(
std::unique_ptr<FrameSinkHolder> frame_sink_holder,
aura::Window* host_window);
void set_presentation_callback(PresentationCallback callback) {
presentation_callback_ = std::move(callback);
}
base::WeakPtr<FrameSinkHolder> GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
void SetAutoUpdateMode(bool mode);
UiResourceManager& resource_manager() { return resources_manager_; }
void SubmitCompositorFrame(bool synchronous_draw);
void SetBeginFrameSource(viz::BeginFrameSource* source) override;
std::optional<viz::HitTestRegionList> BuildHitTestData() override;
void ReclaimResources(std::vector<viz::ReturnedResource> resources) override;
void SetTreeActivationCallback(base::RepeatingClosure callback) override;
void DidReceiveCompositorFrameAck() override;
void DidPresentCompositorFrame(
uint32_t frame_token,
const viz::FrameTimingDetails& details) override;
void DidLoseLayerTreeFrameSink() override;
void OnDraw(const gfx::Transform& transform,
const gfx::Rect& viewport,
bool resourceless_software_draw,
bool skip_draw) override;
void SetMemoryPolicy(const cc::ManagedMemoryPolicy& policy) override;
void SetExternalTilePriorityConstraints(
const gfx::Rect& viewport_rect,
const gfx::Transform& transform) override;
void OnBeginFrameSourcePausedChanged(bool paused) override;
bool OnBeginFrameDerivedImpl(const viz::BeginFrameArgs& args) override;
void OnWindowDestroying(aura::Window* window) override;
private:
friend class FrameSinkHolderTestApi;
void ObserveBeginFrameSource(bool start);
void MaybeStopObservingBeingFrameSource();
void DidNotProduceFrame(viz::BeginFrameAck&& begin_frame_ack,
cc::FrameSkippedReason reason);
viz::CompositorFrame CreateEmptyFrame();
void SubmitCompositorFrameInternal(
std::unique_ptr<viz::CompositorFrame> frame);
void ScheduleDelete();
bool WaitingToScheduleDelete() const;
void SetRootWindowForDeletion(aura::Window* root_window);
bool first_frame_requested() const {
return !on_first_frame_requested_callback_;
}
std::unique_ptr<cc::LayerTreeFrameSink> frame_sink_;
raw_ptr<viz::BeginFrameSource> begin_frame_source_ = nullptr;
bool pending_compositor_frame_ack_ = false;
bool pending_compositor_frame_ = false;
gfx::Size last_frame_size_in_pixels_;
float last_frame_device_scale_factor_ = 1.0f;
UiResourceManager resources_manager_;
viz::FrameTokenGenerator compositor_frame_token_generator_;
bool delete_pending_ = false;
bool auto_update_ = false;
PresentationCallback presentation_callback_;
GetCompositorFrameCallback get_compositor_frame_callback_;
OnFirstFrameRequestedCallback on_first_frame_requested_callback_;
OnFrameSinkLost on_frame_sink_lost_callback_;
bool is_frame_sink_lost_ = false;
base::ScopedObservation<aura::Window, aura::WindowObserver>
root_window_observation_{this};
base::ScopedObservation<viz::BeginFrameSource, viz::BeginFrameObserver>
begin_frame_observation_{this};
int consecutive_begin_frames_produced_no_frame_count_ = 0;
base::WeakPtrFactory<FrameSinkHolder> weak_ptr_factory_{this};
};
}
#endif