| // Copyright 2017 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 GARNET_LIB_UI_GFX_ENGINE_SESSION_H_ |
| #define GARNET_LIB_UI_GFX_ENGINE_SESSION_H_ |
| |
| #include <vector> |
| |
| #include <fuchsia/ui/gfx/cpp/fidl.h> |
| #include <fuchsia/ui/scenic/cpp/fidl.h> |
| |
| #include "garnet/lib/ui/gfx/engine/gfx_command_applier.h" |
| #include "garnet/lib/ui/gfx/engine/resource_map.h" |
| #include "garnet/lib/ui/gfx/engine/session_context.h" |
| #include "garnet/lib/ui/gfx/engine/session_manager.h" |
| #include "garnet/lib/ui/gfx/id.h" |
| #include "garnet/lib/ui/gfx/resources/memory.h" |
| #include "garnet/lib/ui/gfx/resources/resource_context.h" |
| #include "garnet/lib/ui/scenic/event_reporter.h" |
| #include "garnet/lib/ui/scenic/util/error_reporter.h" |
| #include "garnet/lib/ui/scenic/util/print_command.h" |
| #include "lib/escher/flib/fence_set_listener.h" |
| #include "lib/fxl/memory/weak_ptr.h" |
| #include "lib/fxl/tasks/task_runner.h" |
| |
| namespace scenic_impl { |
| namespace gfx { |
| |
| class ImagePipe; |
| using ImagePipePtr = fxl::RefPtr<ImagePipe>; |
| |
| class CommandContext; |
| class Engine; |
| class Resource; |
| |
| // gfx::Session is the internal endpoint of the scenic::Session channel. |
| // It owns, and is responsible for, all graphics state on the channel |
| class Session { |
| public: |
| // Return type for ApplyScheduledUpdate |
| struct ApplyUpdateResult { |
| bool success; |
| bool needs_render; |
| }; |
| |
| Session(SessionId id, SessionContext context, |
| EventReporter* event_reporter = EventReporter::Default(), |
| ErrorReporter* error_reporter = ErrorReporter::Default()); |
| virtual ~Session(); |
| |
| // Apply the operation to the current session state. Return true if |
| // successful, and false if the op is somehow invalid. In the latter case, |
| // the Session is left unchanged. |
| bool ApplyCommand(CommandContext* command_context, |
| fuchsia::ui::gfx::Command command) { |
| return GfxCommandApplier::ApplyCommand(this, command_context, |
| std::move(command)); |
| } |
| |
| SessionId id() const { return id_; } |
| |
| const fxl::WeakPtr<Session> GetWeakPtr() { |
| return weak_factory_.GetWeakPtr(); |
| } |
| const SessionContext& session_context() const { return session_context_; } |
| const ResourceContext& resource_context() const { return resource_context_; } |
| |
| // Return the total number of existing resources associated with this Session. |
| size_t GetTotalResourceCount() const { return resource_count_; } |
| |
| // Return the number of resources that a client can identify via a |
| // ResourceId. This number is decremented when a |
| // ReleaseResourceCmd is applied. However, the resource may continue to |
| // exist if it is referenced by other resources. |
| size_t GetMappedResourceCount() const { return resources_.size(); } |
| |
| ErrorReporter* error_reporter() const; // Never nullptr. |
| EventReporter* event_reporter() const; // Never nullptr. |
| |
| ResourceMap* resources() { return &resources_; } |
| |
| // Called by SessionHandler::Present(). Stashes the arguments without |
| // applying them; they will later be applied by ApplyScheduledUpdates(). |
| bool ScheduleUpdate(uint64_t presentation_time, |
| std::vector<::fuchsia::ui::gfx::Command> commands, |
| std::vector<zx::event> acquire_fences, |
| std::vector<zx::event> release_fences, |
| fuchsia::ui::scenic::Session::PresentCallback callback); |
| |
| // Called by ImagePipe::PresentImage(). Stashes the arguments without |
| // applying them; they will later be applied by ApplyScheduledUpdates(). |
| void ScheduleImagePipeUpdate(uint64_t presentation_time, |
| ImagePipePtr image_pipe); |
| |
| // Called by Engine() when it is notified by the FrameScheduler that |
| // a frame should be rendered for the specified |presentation_time|. |
| // Returns ApplyUpdateResult.success as true if updates were successfully |
| // applied, false if updates failed to be applied. |
| // Returns ApplyUpdateResult.needs_render as true if any changes were |
| // applied, false if none were. |
| ApplyUpdateResult ApplyScheduledUpdates(CommandContext* command_context, |
| uint64_t presentation_time, |
| uint64_t presentation_interval); |
| |
| // Convenience. Forwards an event to the EventReporter. |
| void EnqueueEvent(::fuchsia::ui::gfx::Event event); |
| void EnqueueEvent(::fuchsia::ui::input::InputEvent event); |
| |
| // Called by SessionHandler::HitTest(). |
| void HitTest(uint32_t node_id, fuchsia::ui::gfx::vec3 ray_origin, |
| fuchsia::ui::gfx::vec3 ray_direction, |
| fuchsia::ui::scenic::Session::HitTestCallback callback); |
| |
| // Called by SessionHandler::HitTestDeviceRay(). |
| void HitTestDeviceRay(::fuchsia::ui::gfx::vec3 ray_origin, |
| fuchsia::ui::gfx::vec3 ray_direction, |
| fuchsia::ui::scenic::Session::HitTestCallback callback); |
| |
| void SetDebugName(const std::string& debug_name) { debug_name_ = debug_name; } |
| |
| private: |
| friend class Resource; |
| void IncrementResourceCount() { ++resource_count_; } |
| void DecrementResourceCount() { --resource_count_; } |
| |
| struct Update { |
| uint64_t presentation_time; |
| |
| std::vector<::fuchsia::ui::gfx::Command> commands; |
| std::unique_ptr<escher::FenceSetListener> acquire_fences; |
| std::vector<zx::event> release_fences; |
| |
| // Callback to report when the update has been applied in response to |
| // an invocation of |Session.Present()|. |
| fuchsia::ui::scenic::Session::PresentCallback present_callback; |
| }; |
| bool ApplyUpdate(CommandContext* command_context, |
| std::vector<::fuchsia::ui::gfx::Command> commands); |
| std::queue<Update> scheduled_updates_; |
| std::vector<zx::event> fences_to_release_on_next_update_; |
| |
| uint64_t last_applied_update_presentation_time_ = 0; |
| uint64_t last_presentation_time_ = 0; |
| |
| struct ImagePipeUpdate { |
| uint64_t presentation_time; |
| ImagePipePtr image_pipe; |
| |
| bool operator>(const ImagePipeUpdate& rhs) const { |
| return presentation_time > rhs.presentation_time; |
| } |
| }; |
| // The least element should be on top. |
| std::priority_queue<ImagePipeUpdate, std::vector<ImagePipeUpdate>, |
| std::greater<ImagePipeUpdate>> |
| scheduled_image_pipe_updates_; |
| |
| const SessionId id_; |
| std::string debug_name_; |
| ErrorReporter* error_reporter_ = nullptr; |
| EventReporter* event_reporter_ = nullptr; |
| |
| // Context objects should be above ResourceMap so they are destroyed after |
| // Resources; their lifecycle must exceed that of the Resources. |
| SessionContext session_context_; |
| ResourceContext resource_context_; |
| ResourceMap resources_; |
| size_t resource_count_ = 0; |
| |
| fxl::WeakPtrFactory<Session> weak_factory_; // must be last |
| }; |
| |
| } // namespace gfx |
| } // namespace scenic_impl |
| |
| #endif // GARNET_LIB_UI_GFX_ENGINE_SESSION_H_ |