blob: 4322cbe5e5a749972ee48d504778a7eb22ba16f8 [file] [log] [blame]
// Copyright 2020 The Fuchsia 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 SRC_UI_SCENIC_LIB_FLATLAND_FLATLAND_MANAGER_H_
#define SRC_UI_SCENIC_LIB_FLATLAND_FLATLAND_MANAGER_H_
#include <fuchsia/ui/composition/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/async/cpp/executor.h>
#include <lib/async/default.h>
#include <lib/fidl/cpp/binding.h>
#include <map>
#include <mutex>
#include <thread>
#include <unordered_map>
#include "src/ui/scenic/lib/display/display.h"
#include "src/ui/scenic/lib/flatland/flatland.h"
#include "src/ui/scenic/lib/flatland/flatland_display.h"
#include "src/ui/scenic/lib/flatland/flatland_presenter.h"
#include "src/ui/scenic/lib/flatland/link_system.h"
#include "src/ui/scenic/lib/flatland/uber_struct_system.h"
#include "src/ui/scenic/lib/scheduling/frame_scheduler.h"
#include "src/ui/scenic/lib/scheduling/id.h"
#include "src/ui/scenic/lib/utils/dispatcher_holder.h"
namespace flatland {
class FlatlandManager {
public:
FlatlandManager(
async_dispatcher_t* dispatcher, const std::shared_ptr<FlatlandPresenter>& flatland_presenter,
const std::shared_ptr<UberStructSystem>& uber_struct_system,
const std::shared_ptr<LinkSystem>& link_system,
std::shared_ptr<scenic_impl::display::Display> display,
std::vector<std::shared_ptr<allocation::BufferCollectionImporter>>
buffer_collection_importers,
fit::function<void(fidl::InterfaceRequest<fuchsia::ui::views::Focuser>, zx_koid_t)>
register_view_focuser,
fit::function<void(fidl::InterfaceRequest<fuchsia::ui::views::ViewRefFocused>, zx_koid_t)>
register_view_ref_focused,
fit::function<void(fidl::InterfaceRequest<fuchsia::ui::pointer::TouchSource>, zx_koid_t)>
register_touch_source,
fit::function<void(fidl::InterfaceRequest<fuchsia::ui::pointer::MouseSource>, zx_koid_t)>
register_mouse_source);
~FlatlandManager();
scheduling::SessionId CreateFlatland(
fidl::InterfaceRequest<fuchsia::ui::composition::Flatland> flatland);
// TODO(https://fxbug.dev/42156949): this creates a FlatlandDisplay attached to the "primary" hardware
// display (i.e. the only one supported). In the future there will be APIs that allow clients to
// enumerate the displays, and to allow creation of a FlatlandDisplay bound to a specific one of
// them. For now, attempts to create a second concurrent FlatlandDisplay (or
// gfx::DisplayCompositor) will fail.
void CreateFlatlandDisplay(
fidl::InterfaceRequest<fuchsia::ui::composition::FlatlandDisplay> flatland);
// Called at FrameScheduler UpdateSessions time.
void UpdateInstances(
const std::unordered_map<scheduling::SessionId, scheduling::PresentId>& instance_to_update);
// Called at FrameScheduler OnCpuWorkDone time.
void SendHintsToStartRendering();
// Called at FrameScheduler OnFramePresented time.
void OnFramePresented(
const std::unordered_map<scheduling::SessionId,
std::map<scheduling::PresentId, /*latched_time*/ zx::time>>&
latched_times,
scheduling::PresentTimestamps present_times);
// For validating test logic.
// Sessions still "owned" by FlatlandManager.
size_t GetSessionCount() const;
// Sessions still alive (but which might have been remove from FlatlandManager).
size_t GetAliveSessionCount() const { return alive_sessions_; }
// TODO(https://fxbug.dev/42156949): This is a temporary method assuming that there are either 0 or 1
// displays with attached Flatland content. Used by TemporaryFrameRendererDelegator: if no
// FlatlandDisplay is found, then it assumes that there might be "Gfx" content to render.
std::shared_ptr<FlatlandDisplay> GetPrimaryFlatlandDisplayForRendering();
private:
// Represents an individual Flatland session for a client.
struct FlatlandInstance {
// The looper for this Flatland instance, which will be run on a worker thread spawned by the
// async::Loop itself. It must be the first member of this struct so that |impl| is
// destroyed first in the default destruction order, else it will attempt to run on a shutdown
// looper.
std::shared_ptr<utils::LoopDispatcherHolder> loop;
// The implementation of Flatland, which includes the bindings for the instance. This must come
// before |peer_closed_waiter| so that the Wait is destroyed, and therefore cancelled, before
// the impl is destroyed in the default destruction order.
std::shared_ptr<Flatland> impl;
// Tracks the first time we return credits to the client.
bool initial_credits_returned = false;
};
// TODO(https://fxbug.dev/42156567): there's quite some overlap with FlatlandInstance. Can they be unified?
// Perhaps name the unified struct "FlatlandApiInstance"?
struct FlatlandDisplayInstance {
// The looper for this Flatland display, which will be run on a worker thread spawned by the
// async::Loop itself. It must be the first member of this struct so that |impl| is
// destroyed first in the default destruction order, else it will attempt to run on a shutdown
// looper.
std::shared_ptr<utils::LoopDispatcherHolder> loop;
std::shared_ptr<FlatlandDisplay> impl;
std::shared_ptr<scenic_impl::display::Display> display;
};
// Sends |additional_present_credits| to a particular Flatland |instance|.
void SendPresentCredits(FlatlandInstance* instance, uint32_t additional_present_credits,
Flatland::FuturePresentationInfos presentation_infos);
// Sends the OnFramePresented event to a particular Flatland |instance|.
void SendFramePresented(
FlatlandInstance* instance,
const std::map<scheduling::PresentId, /*latched_time*/ zx::time>& latched_times,
scheduling::PresentTimestamps present_times);
// Removes the Flatland instance associated with |session_id|.
void RemoveFlatlandInstance(scheduling::SessionId session_id);
// The function passed into a Flatland constructor that allows the Flatland instance to trigger
// its own destruction when the client makes an unrecoverable error. This function will be called
// on Flatland instance worker threads.
void DestroyInstanceFunction(scheduling::SessionId session_id);
std::shared_ptr<Flatland> NewFlatland(
std::shared_ptr<utils::DispatcherHolder> dispatcher_holder,
fidl::InterfaceRequest<fuchsia::ui::composition::Flatland> request,
scheduling::SessionId session_id, std::function<void()> destroy_instance_function,
std::shared_ptr<FlatlandPresenter> flatland_presenter,
std::shared_ptr<LinkSystem> link_system,
std::shared_ptr<UberStructSystem::UberStructQueue> uber_struct_queue,
const std::vector<std::shared_ptr<allocation::BufferCollectionImporter>>&
buffer_collection_importers) const;
// Used to assert that code is running on the expected thread.
void CheckIsOnMainThread() const {
FX_DCHECK(executor_.dispatcher() == async_get_default_dispatcher());
}
std::shared_ptr<FlatlandPresenter> flatland_presenter_;
std::shared_ptr<UberStructSystem> uber_struct_system_;
std::shared_ptr<LinkSystem> link_system_;
std::vector<std::shared_ptr<allocation::BufferCollectionImporter>> buffer_collection_importers_;
std::unordered_map<scheduling::SessionId, /*additional_present_credits*/ uint32_t>
flatland_instances_updated_;
// FlatlandInstances are not moveable (because fidl::Binding is not movable), therefore are reffed
// by unique_ptr which can be moved if the map needs to do an internal reallocation.
std::unordered_map<scheduling::SessionId, std::unique_ptr<FlatlandInstance>> flatland_instances_;
// FlatlandDisplayInstances are not moveable (because fidl::Binding is not movable), therefore are
// reffed by unique_ptr which can be moved if the map needs to do an internal reallocation.
std::unordered_map<scheduling::SessionId, std::unique_ptr<FlatlandDisplayInstance>>
flatland_display_instances_;
// Eventually we will support multiple displays, but as we bootstrap Flatland we assume that
// there is a single primary display.
std::shared_ptr<scenic_impl::display::Display> primary_display_;
// The number of flatland instances currently alive. Used to ensure that the flatland manager gets
// destroyed after all instances in |flatland_instances_| and |flatland_display_instances_| are
// destroyed.
std::atomic<uint32_t> alive_sessions_ = 0;
// Callbacks for registering View-bound protocols.
fit::function<void(fidl::InterfaceRequest<fuchsia::ui::views::Focuser>, zx_koid_t)>
register_view_focuser_;
fit::function<void(fidl::InterfaceRequest<fuchsia::ui::views::ViewRefFocused>, zx_koid_t)>
register_view_ref_focused_;
fit::function<void(fidl::InterfaceRequest<fuchsia::ui::pointer::TouchSource>, zx_koid_t)>
register_touch_source_;
fit::function<void(fidl::InterfaceRequest<fuchsia::ui::pointer::MouseSource>, zx_koid_t)>
register_mouse_source_;
// This loop executes tasks related to shutting down Flatland sessions and FlatlandDisplays.
// It avoids potential jank that might be caused by executing these on the main thread, and
// also lets the ~FlatlandManager() destructor spin until all of these tasks are completed.
async::Loop cleanup_loop_;
// Stores and executes async tasks on the dispatcher provided in this object's constructor.
// NOTE: This object MUST BE the final member of this class to ensure that async tasks are
// cancelled and destroyed first during destruction, else they might access already-destroyed
// members.
async::Executor executor_;
};
} // namespace flatland
#endif // SRC_UI_SCENIC_LIB_FLATLAND_FLATLAND_MANAGER_H_