blob: 3996b6550a6c3e1f38c134f626f6b9f202be182d [file] [log] [blame]
// Copyright 2018 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_SCENIC_SESSION_H_
#define SRC_UI_SCENIC_LIB_SCENIC_SESSION_H_
#include <fuchsia/ui/gfx/cpp/fidl.h>
#include <lib/fit/function.h>
#include <array>
#include <memory>
#include <string>
#include "src/lib/fxl/macros.h"
#include "src/lib/fxl/memory/weak_ptr.h"
#include "src/ui/scenic/lib/scenic/event_reporter.h"
#include "src/ui/scenic/lib/scenic/forward_declarations.h"
#include "src/ui/scenic/lib/scenic/scenic.h"
#include "src/ui/scenic/lib/scenic/system.h"
#include "src/ui/scenic/lib/scenic/util/error_reporter.h"
namespace scenic_impl {
class CommandDispatcher;
class Scenic;
using SessionId = uint64_t;
using OnFramePresentedCallback =
fit::function<void(fuchsia::scenic::scheduling::FramePresentedInfo info)>;
class Session final : public fuchsia::ui::scenic::Session {
public:
Session(SessionId id, fidl::InterfaceRequest<fuchsia::ui::scenic::Session> session_request,
fidl::InterfaceHandle<fuchsia::ui::scenic::SessionListener> listener);
~Session() override;
void SetCommandDispatchers(
std::array<CommandDispatcherUniquePtr, System::TypeId::kMaxSystems> dispatchers);
// |fuchsia::ui::scenic::Session|
void Enqueue(std::vector<fuchsia::ui::scenic::Command> cmds) override;
// |fuchsia::ui::scenic::Session|
void Present(uint64_t presentation_time, std::vector<zx::event> acquire_fences,
std::vector<zx::event> release_fences, PresentCallback callback) override;
// |fuchsia::ui::scenic::Session|
void Present2(fuchsia::ui::scenic::Present2Args args, Present2Callback callback) override;
// |fuchsia::ui::scenic::Session|
void RequestPresentationTimes(zx_duration_t requested_prediction_span,
RequestPresentationTimesCallback callback) override;
// |fuchsia::ui::scenic::Session|
void SetDebugName(std::string debug_name) override;
void SetFrameScheduler(const std::shared_ptr<scheduling::FrameScheduler>& frame_scheduler);
SessionId id() const { return id_; }
std::shared_ptr<ErrorReporter> error_reporter() const { return reporter_; }
std::shared_ptr<EventReporter> event_reporter() const { return reporter_; }
// For tests. See FlushEvents() below.
void set_event_callback(fit::function<void(fuchsia::ui::scenic::Event)> callback) {
reporter_->set_event_callback(std::move(callback));
}
// For tests. Called by ReportError().
void set_error_callback(fit::function<void(std::string)> callback) {
reporter_->set_error_callback(std::move(callback));
}
bool is_bound() { return binding_.is_bound(); }
void set_binding_error_handler(fit::function<void(zx_status_t)> error_handler);
// Clients cannot call Present() anymore when |presents_in_flight_| reaches this value. Scenic
// uses this to apply backpressure to clients.
static constexpr int64_t kMaxPresentsInFlight = 5;
private:
// Helper class which manages the reporting of events and errors to Scenic clients.
// NOTE: this object is not only reffed by the owning Session; it is also reffed by
// shared_ptr<EventReporter/ErrorReporter> that are obtained via CommandDispatcherContext.
// Therefore, the owning Session cannot be strongly reffed by this, or else a reference-cycle
// would result.
class EventAndErrorReporter : public EventReporter, public ErrorReporter {
public:
explicit EventAndErrorReporter(Session* session);
virtual ~EventAndErrorReporter() = default;
// |EventReporter|
// Enqueues the gfx/cmd event and schedules call to FlushEvents().
void EnqueueEvent(fuchsia::ui::gfx::Event event) override;
void EnqueueEvent(fuchsia::ui::scenic::Command event) override;
// |EventReporter|
// Enqueues the input event and immediately calls FlushEvents().
void EnqueueEvent(fuchsia::ui::input::InputEvent event) override;
// |EventReporter|
EventReporterWeakPtr GetWeakPtr() override { return weak_factory_.GetWeakPtr(); }
// |ErrorReporter|
// Customize behavior of ErrorReporter::ReportError().
void ReportError(fxl::LogSeverity severity, std::string error_string) override;
// Called when the owning session is destroyed.
void Reset();
void set_event_callback(fit::function<void(fuchsia::ui::scenic::Event)> callback) {
event_callback_ = std::move(callback);
}
// For tests. Called by ReportError().
void set_error_callback(fit::function<void(std::string)> callback) {
error_callback_ = std::move(callback);
}
void FlushEvents();
// Post an asynchronous task to call FlushEvents.
void PostFlushTask();
private:
Session* session_ = nullptr;
// Callbacks for testing.
fit::function<void(fuchsia::ui::scenic::Event)> event_callback_;
fit::function<void(std::string)> error_callback_;
// Holds events from EnqueueEvent() until they are flushed by FlushEvents().
std::vector<fuchsia::ui::scenic::Event> buffered_events_;
fxl::WeakPtrFactory<EventAndErrorReporter> weak_factory_;
};
// Flush any/all events that were enqueued via EnqueueEvent(), sending them
// to |listener_|. If |listener_| is null but |event_callback_| isn't, then
// invoke the callback for each event.
void FlushEvents() { reporter_->FlushEvents(); }
// Gets the future presentation times from the frame scheduler (indirectly),
// and invokes |callback|.
void InvokeFuturePresentationTimesCallback(zx_duration_t requested_prediction_span,
RequestPresentationTimesCallback callback);
// True until we are in the process of being destroyed.
bool valid_ = true;
const SessionId id_;
fidl::InterfacePtr<fuchsia::ui::scenic::SessionListener> listener_;
std::array<CommandDispatcherUniquePtr, System::TypeId::kMaxSystems> dispatchers_;
std::weak_ptr<scheduling::FrameScheduler> frame_scheduler_;
// A flow event trace id for following |Session::Present| calls from client
// to scenic. This will be incremented each |Session::Present| call. By
// convention, the scenic implementation side will also contain its own
// trace id that begins at 0, and is incremented each |Session::Present|
// call.
uint64_t next_present_trace_id_ = 0;
int64_t num_presents_allowed_ = kMaxPresentsInFlight;
TempSessionDelegate* GetTempSessionDelegate();
std::shared_ptr<EventAndErrorReporter> reporter_;
fidl::Binding<fuchsia::ui::scenic::Session> binding_;
fxl::WeakPtrFactory<Session> weak_factory_;
FXL_DISALLOW_COPY_AND_ASSIGN(Session);
};
} // namespace scenic_impl
#endif // SRC_UI_SCENIC_LIB_SCENIC_SESSION_H_