blob: cd9e90ce9b93ca87faf90db7ac92661a716bbfdd [file] [log] [blame]
// 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 "garnet/lib/ui/gfx/engine/engine.h"
#include "garnet/lib/ui/gfx/engine/resource_map.h"
#include "garnet/lib/ui/gfx/id.h"
#include "garnet/lib/ui/gfx/resources/memory.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 Image;
using ImagePtr = ::fxl::RefPtr<Image>;
class ImageBase;
using ImageBasePtr = ::fxl::RefPtr<ImageBase>;
class ImagePipe;
using ImagePipePtr = ::fxl::RefPtr<ImagePipe>;
class Session;
using SessionPtr = ::fxl::RefPtr<Session>;
class Engine;
class Resource;
class SessionHandler;
// TODO: use unsafe ref-counting for better performance (our architecture
// guarantees that this is safe).
class Session : public fxl::RefCountedThreadSafe<Session> {
public:
Session(SessionId id, Engine* engine,
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(::fuchsia::ui::gfx::Command command);
SessionId id() const { return id_; }
Engine* engine() const { return engine_; }
escher::Escher* escher() const { return engine_->escher(); }
// 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(); }
// Session becomes invalid once TearDown is called.
bool is_valid() const { return is_valid_; }
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,
::fidl::VectorPtr<zx::event> acquire_fences,
::fidl::VectorPtr<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|. Return
// true if any updates were applied, and false otherwise.
bool ApplyScheduledUpdates(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; }
protected:
friend class SessionHandler;
// Called only by SessionHandler. Use BeginTearDown() instead when you need to
// teardown from within Session. Virtual to allow test subclasses to override.
//
// The chain of events is:
// Session::BeginTearDown or SessionHandler::BeginTearDown
// => Engine::TearDownSession
// => SessionHandler::TearDown
// => Session::TearDown
//
// We are guaranteed that by the time TearDown() is closed, SessionHandler
// has destroyed the channel to this session.
virtual void TearDown();
private:
// Called internally to initiate teardown.
void BeginTearDown();
// Cmderation application functions, called by ApplyCommand().
bool ApplyCreateResourceCmd(::fuchsia::ui::gfx::CreateResourceCmd command);
bool ApplyReleaseResourceCmd(::fuchsia::ui::gfx::ReleaseResourceCmd command);
bool ApplyExportResourceCmd(::fuchsia::ui::gfx::ExportResourceCmd command);
bool ApplyImportResourceCmd(::fuchsia::ui::gfx::ImportResourceCmd command);
bool ApplyAddChildCmd(::fuchsia::ui::gfx::AddChildCmd command);
bool ApplyAddPartCmd(::fuchsia::ui::gfx::AddPartCmd command);
bool ApplyDetachCmd(::fuchsia::ui::gfx::DetachCmd command);
bool ApplyDetachChildrenCmd(::fuchsia::ui::gfx::DetachChildrenCmd command);
bool ApplySetTagCmd(::fuchsia::ui::gfx::SetTagCmd command);
bool ApplySetTranslationCmd(::fuchsia::ui::gfx::SetTranslationCmd command);
bool ApplySetScaleCmd(::fuchsia::ui::gfx::SetScaleCmd command);
bool ApplySetRotationCmd(::fuchsia::ui::gfx::SetRotationCmd command);
bool ApplySetAnchorCmd(::fuchsia::ui::gfx::SetAnchorCmd command);
bool ApplySetSizeCmd(::fuchsia::ui::gfx::SetSizeCmd command);
bool ApplySetOpacityCmd(::fuchsia::ui::gfx::SetOpacityCmd command);
bool ApplySendSizeChangeHintCmd(
::fuchsia::ui::gfx::SendSizeChangeHintCmdHACK command);
bool ApplySetShapeCmd(::fuchsia::ui::gfx::SetShapeCmd command);
bool ApplySetMaterialCmd(::fuchsia::ui::gfx::SetMaterialCmd command);
bool ApplySetClipCmd(::fuchsia::ui::gfx::SetClipCmd command);
bool ApplySetViewPropertiesCmd(
::fuchsia::ui::gfx::SetViewPropertiesCmd command);
bool ApplySetHitTestBehaviorCmd(
::fuchsia::ui::gfx::SetHitTestBehaviorCmd command);
bool ApplySetCameraCmd(::fuchsia::ui::gfx::SetCameraCmd command);
bool ApplySetCameraTransformCmd(
::fuchsia::ui::gfx::SetCameraTransformCmd command);
bool ApplySetCameraProjectionCmd(
::fuchsia::ui::gfx::SetCameraProjectionCmd command);
bool ApplySetStereoCameraProjectionCmd(
::fuchsia::ui::gfx::SetStereoCameraProjectionCmd command);
bool ApplySetCameraPoseBufferCmd(
::fuchsia::ui::gfx::SetCameraPoseBufferCmd command);
bool ApplySetLightColorCmd(::fuchsia::ui::gfx::SetLightColorCmd command);
bool ApplySetLightDirectionCmd(
::fuchsia::ui::gfx::SetLightDirectionCmd command);
bool ApplyAddLightCmd(::fuchsia::ui::gfx::AddLightCmd command);
bool ApplyDetachLightCmd(::fuchsia::ui::gfx::DetachLightCmd command);
bool ApplyDetachLightsCmd(::fuchsia::ui::gfx::DetachLightsCmd command);
bool ApplySetTextureCmd(::fuchsia::ui::gfx::SetTextureCmd command);
bool ApplySetColorCmd(::fuchsia::ui::gfx::SetColorCmd command);
bool ApplyBindMeshBuffersCmd(::fuchsia::ui::gfx::BindMeshBuffersCmd command);
bool ApplyAddLayerCmd(::fuchsia::ui::gfx::AddLayerCmd command);
bool ApplyRemoveLayerCmd(::fuchsia::ui::gfx::RemoveLayerCmd command);
bool ApplyRemoveAllLayersCmd(::fuchsia::ui::gfx::RemoveAllLayersCmd command);
bool ApplySetLayerStackCmd(::fuchsia::ui::gfx::SetLayerStackCmd command);
bool ApplySetRendererCmd(::fuchsia::ui::gfx::SetRendererCmd command);
bool ApplySetRendererParamCmd(
::fuchsia::ui::gfx::SetRendererParamCmd command);
bool ApplySetEventMaskCmd(::fuchsia::ui::gfx::SetEventMaskCmd command);
bool ApplySetLabelCmd(::fuchsia::ui::gfx::SetLabelCmd command);
bool ApplySetDisableClippingCmd(
::fuchsia::ui::gfx::SetDisableClippingCmd command);
// Resource creation functions, called by ApplyCreateResourceCmd().
bool ApplyCreateMemory(ResourceId id, ::fuchsia::ui::gfx::MemoryArgs args);
bool ApplyCreateImage(ResourceId id, ::fuchsia::ui::gfx::ImageArgs args);
bool ApplyCreateImagePipe(ResourceId id,
::fuchsia::ui::gfx::ImagePipeArgs args);
bool ApplyCreateBuffer(ResourceId id, ::fuchsia::ui::gfx::BufferArgs args);
bool ApplyCreateScene(ResourceId id, ::fuchsia::ui::gfx::SceneArgs args);
bool ApplyCreateCamera(ResourceId id, ::fuchsia::ui::gfx::CameraArgs args);
bool ApplyCreateStereoCamera(ResourceId id,
::fuchsia::ui::gfx::StereoCameraArgs args);
bool ApplyCreateRenderer(ResourceId id,
::fuchsia::ui::gfx::RendererArgs args);
bool ApplyCreateAmbientLight(ResourceId id,
::fuchsia::ui::gfx::AmbientLightArgs args);
bool ApplyCreateDirectionalLight(
ResourceId id, ::fuchsia::ui::gfx::DirectionalLightArgs args);
bool ApplyCreateRectangle(ResourceId id,
::fuchsia::ui::gfx::RectangleArgs args);
bool ApplyCreateRoundedRectangle(
ResourceId id, ::fuchsia::ui::gfx::RoundedRectangleArgs args);
bool ApplyCreateCircle(ResourceId id, ::fuchsia::ui::gfx::CircleArgs args);
bool ApplyCreateMesh(ResourceId id, ::fuchsia::ui::gfx::MeshArgs args);
bool ApplyCreateMaterial(ResourceId id,
::fuchsia::ui::gfx::MaterialArgs args);
bool ApplyCreateView(ResourceId id, ::fuchsia::ui::gfx::ViewArgs args);
bool ApplyCreateViewHolder(ResourceId id,
::fuchsia::ui::gfx::ViewHolderArgs args);
bool ApplyCreateClipNode(ResourceId id,
::fuchsia::ui::gfx::ClipNodeArgs args);
bool ApplyCreateEntityNode(ResourceId id,
::fuchsia::ui::gfx::EntityNodeArgs args);
bool ApplyCreateOpacityNode(ResourceId id,
::fuchsia::ui::gfx::OpacityNodeArgs args);
bool ApplyCreateShapeNode(ResourceId id,
::fuchsia::ui::gfx::ShapeNodeArgs args);
bool ApplyCreateCompositor(ResourceId id,
::fuchsia::ui::gfx::CompositorArgs args);
bool ApplyCreateDisplayCompositor(
ResourceId id, ::fuchsia::ui::gfx::DisplayCompositorArgs args);
bool ApplyCreateImagePipeCompositor(
ResourceId id, ::fuchsia::ui::gfx::ImagePipeCompositorArgs args);
bool ApplyCreateLayerStack(ResourceId id,
::fuchsia::ui::gfx::LayerStackArgs args);
bool ApplyCreateLayer(ResourceId id, ::fuchsia::ui::gfx::LayerArgs args);
bool ApplyCreateVariable(ResourceId id,
::fuchsia::ui::gfx::VariableArgs args);
bool ApplyTakeSnapshotCmdHACK(
::fuchsia::ui::gfx::TakeSnapshotCmdHACK command);
// Actually create resources.
ResourcePtr CreateMemory(ResourceId id, ::fuchsia::ui::gfx::MemoryArgs args);
ResourcePtr CreateImage(ResourceId id, MemoryPtr memory,
::fuchsia::ui::gfx::ImageArgs args);
ResourcePtr CreateBuffer(ResourceId id, MemoryPtr memory,
uint32_t memory_offset, uint32_t num_bytes);
ResourcePtr CreateScene(ResourceId id, ::fuchsia::ui::gfx::SceneArgs args);
ResourcePtr CreateCamera(ResourceId id, ::fuchsia::ui::gfx::CameraArgs args);
ResourcePtr CreateStereoCamera(ResourceId id,
::fuchsia::ui::gfx::StereoCameraArgs args);
ResourcePtr CreateRenderer(ResourceId id,
::fuchsia::ui::gfx::RendererArgs args);
ResourcePtr CreateAmbientLight(ResourceId id);
ResourcePtr CreateDirectionalLight(ResourceId id);
ResourcePtr CreateView(ResourceId id, ::fuchsia::ui::gfx::ViewArgs args);
ResourcePtr CreateViewHolder(ResourceId id,
::fuchsia::ui::gfx::ViewHolderArgs args);
ResourcePtr CreateClipNode(ResourceId id,
::fuchsia::ui::gfx::ClipNodeArgs args);
ResourcePtr CreateEntityNode(ResourceId id,
::fuchsia::ui::gfx::EntityNodeArgs args);
ResourcePtr CreateOpacityNode(ResourceId id,
::fuchsia::ui::gfx::OpacityNodeArgs args);
ResourcePtr CreateShapeNode(ResourceId id,
::fuchsia::ui::gfx::ShapeNodeArgs args);
ResourcePtr CreateCompositor(ResourceId id,
::fuchsia::ui::gfx::CompositorArgs args);
ResourcePtr CreateDisplayCompositor(
ResourceId id, ::fuchsia::ui::gfx::DisplayCompositorArgs args);
ResourcePtr CreateImagePipeCompositor(
ResourceId id, ::fuchsia::ui::gfx::ImagePipeCompositorArgs args);
ResourcePtr CreateLayerStack(ResourceId id,
::fuchsia::ui::gfx::LayerStackArgs args);
ResourcePtr CreateLayer(ResourceId id, ::fuchsia::ui::gfx::LayerArgs args);
ResourcePtr CreateCircle(ResourceId id, float initial_radius);
ResourcePtr CreateRectangle(ResourceId id, float width, float height);
ResourcePtr CreateRoundedRectangle(ResourceId id, float width, float height,
float top_left_radius,
float top_right_radius,
float bottom_right_radius,
float bottom_left_radius);
ResourcePtr CreateMesh(ResourceId id);
ResourcePtr CreateMaterial(ResourceId id);
ResourcePtr CreateVariable(ResourceId id,
::fuchsia::ui::gfx::VariableArgs args);
// Return false and log an error if the value is not of the expected type.
// NOTE: although failure does not halt execution of the program, it does
// indicate client error, and will be used by the caller to tear down the
// Session.
bool AssertValueIsOfType(const ::fuchsia::ui::gfx::Value& value,
const ::fuchsia::ui::gfx::Value::Tag* tags,
size_t tag_count);
template <size_t N>
bool AssertValueIsOfType(
const ::fuchsia::ui::gfx::Value& value,
const std::array<::fuchsia::ui::gfx::Value::Tag, N>& tags) {
return AssertValueIsOfType(value, tags.data(), N);
}
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;
::fidl::VectorPtr<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(std::vector<::fuchsia::ui::gfx::Command> commands);
std::queue<Update> scheduled_updates_;
::fidl::VectorPtr<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_;
Engine* const engine_;
ErrorReporter* error_reporter_ = nullptr;
EventReporter* event_reporter_ = nullptr;
ResourceMap resources_;
size_t resource_count_ = 0;
bool is_valid_ = true;
fxl::WeakPtrFactory<Session> weak_factory_; // must be last
};
} // namespace gfx
} // namespace scenic_impl
#endif // GARNET_LIB_UI_GFX_ENGINE_SESSION_H_