| // 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. |
| |
| #include "lib/ui/scenic/cpp/resources.h" |
| |
| #include <algorithm> |
| |
| #include "lib/images/cpp/images.h" |
| #include "lib/ui/scenic/cpp/commands.h" |
| |
| namespace scenic { |
| namespace { |
| |
| template <class T> |
| constexpr const T& clamp(const T& v, const T& lo, const T& hi) { |
| return (v < lo) ? lo : (hi < v) ? hi : v; |
| } |
| |
| } // namespace |
| |
| Resource::Resource(Session* session) |
| : session_(session), id_(session->AllocResourceId()) {} |
| |
| Resource::Resource(Resource&& moved) |
| : session_(moved.session_), id_(moved.id_) { |
| auto& moved_session = *const_cast<Session**>(&moved.session_); |
| auto& moved_id = *const_cast<uint32_t*>(&moved.id_); |
| moved_session = nullptr; |
| moved_id = 0; |
| } |
| |
| Resource::~Resource() { |
| // If this resource was moved, it is not responsible for releasing the ID. |
| if (session_) |
| session_->ReleaseResource(id_); |
| } |
| |
| void Resource::Export(zx::eventpair export_token) { |
| session_->Enqueue(NewExportResourceCmd(id(), std::move(export_token))); |
| } |
| |
| void Resource::ExportAsRequest(zx::eventpair* out_import_token) { |
| session_->Enqueue(NewExportResourceCmdAsRequest(id(), out_import_token)); |
| } |
| |
| void Resource::SetEventMask(uint32_t event_mask) { |
| session_->Enqueue(NewSetEventMaskCmd(id(), event_mask)); |
| } |
| |
| void Resource::SetLabel(const std::string& label) { |
| session_->Enqueue(NewSetLabelCmd(id(), label)); |
| } |
| |
| Shape::Shape(Session* session) : Resource(session) {} |
| |
| Shape::Shape(Shape&& moved) : Resource(std::move(moved)) {} |
| |
| Shape::~Shape() = default; |
| |
| Circle::Circle(Session* session, float radius) : Shape(session) { |
| session->Enqueue(NewCreateCircleCmd(id(), radius)); |
| } |
| |
| Circle::Circle(Circle&& moved) : Shape(std::move(moved)) {} |
| |
| Circle::~Circle() = default; |
| |
| Rectangle::Rectangle(Session* session, float width, float height) |
| : Shape(session) { |
| session->Enqueue(NewCreateRectangleCmd(id(), width, height)); |
| } |
| |
| Rectangle::Rectangle(Rectangle&& moved) : Shape(std::move(moved)) {} |
| |
| Rectangle::~Rectangle() = default; |
| |
| RoundedRectangle::RoundedRectangle(Session* session, float width, float height, |
| float top_left_radius, |
| float top_right_radius, |
| float bottom_right_radius, |
| float bottom_left_radius) |
| : Shape(session) { |
| session->Enqueue(NewCreateRoundedRectangleCmd( |
| id(), width, height, top_left_radius, top_right_radius, |
| bottom_right_radius, bottom_left_radius)); |
| } |
| |
| RoundedRectangle::RoundedRectangle(RoundedRectangle&& moved) |
| : Shape(std::move(moved)) {} |
| |
| RoundedRectangle::~RoundedRectangle() = default; |
| |
| Image::Image(const Memory& memory, off_t memory_offset, |
| fuchsia::images::ImageInfo info) |
| : Image(memory.session(), memory.id(), memory_offset, std::move(info)) {} |
| |
| Image::Image(Session* session, uint32_t memory_id, off_t memory_offset, |
| fuchsia::images::ImageInfo info) |
| : Resource(session), memory_offset_(memory_offset), info_(info) { |
| session->Enqueue( |
| NewCreateImageCmd(id(), memory_id, memory_offset_, std::move(info))); |
| } |
| |
| Image::Image(Image&& moved) |
| : Resource(std::move(moved)), |
| memory_offset_(moved.memory_offset_), |
| info_(moved.info_) {} |
| |
| Image::~Image() = default; |
| |
| size_t Image::ComputeSize(const fuchsia::images::ImageInfo& image_info) { |
| return images::ImageSize(image_info); |
| } |
| |
| Buffer::Buffer(const Memory& memory, off_t memory_offset, size_t num_bytes) |
| : Buffer(memory.session(), memory.id(), memory_offset, num_bytes) {} |
| |
| Buffer::Buffer(Session* session, uint32_t memory_id, off_t memory_offset, |
| size_t num_bytes) |
| : Resource(session) { |
| session->Enqueue( |
| NewCreateBufferCmd(id(), memory_id, memory_offset, num_bytes)); |
| } |
| |
| Buffer::Buffer(Buffer&& moved) : Resource(std::move(moved)) {} |
| |
| Buffer::~Buffer() = default; |
| |
| Memory::Memory(Session* session, zx::vmo vmo, uint64_t allocation_size, |
| fuchsia::images::MemoryType memory_type) |
| : Resource(session), memory_type_(memory_type) { |
| session->Enqueue( |
| NewCreateMemoryCmd(id(), std::move(vmo), allocation_size, memory_type)); |
| } |
| |
| Memory::Memory(Memory&& moved) |
| : Resource(std::move(moved)), memory_type_(moved.memory_type_) {} |
| |
| Memory::~Memory() = default; |
| |
| Mesh::Mesh(Session* session) : Shape(session) { |
| session->Enqueue(NewCreateMeshCmd(id())); |
| } |
| |
| Mesh::Mesh(Mesh&& moved) : Shape(std::move(moved)) {} |
| |
| Mesh::~Mesh() = default; |
| |
| void Mesh::BindBuffers(const Buffer& index_buffer, |
| fuchsia::ui::gfx::MeshIndexFormat index_format, |
| uint64_t index_offset, uint32_t index_count, |
| const Buffer& vertex_buffer, |
| fuchsia::ui::gfx::MeshVertexFormat vertex_format, |
| uint64_t vertex_offset, uint32_t vertex_count, |
| const float bounding_box_min[3], |
| const float bounding_box_max[3]) { |
| ZX_DEBUG_ASSERT(session() == index_buffer.session() && |
| session() == vertex_buffer.session()); |
| session()->Enqueue(NewBindMeshBuffersCmd( |
| id(), index_buffer.id(), index_format, index_offset, index_count, |
| vertex_buffer.id(), std::move(vertex_format), vertex_offset, vertex_count, |
| bounding_box_min, bounding_box_max)); |
| } |
| |
| Material::Material(Session* session) : Resource(session) { |
| session->Enqueue(NewCreateMaterialCmd(id())); |
| } |
| |
| Material::Material(Material&& moved) : Resource(std::move(moved)) {} |
| |
| Material::~Material() = default; |
| |
| void Material::SetTexture(uint32_t image_id) { |
| session()->Enqueue(NewSetTextureCmd(id(), image_id)); |
| } |
| |
| void Material::SetColor(uint8_t red, uint8_t green, uint8_t blue, |
| uint8_t alpha) { |
| session()->Enqueue(NewSetColorCmd(id(), red, green, blue, alpha)); |
| } |
| |
| Node::Node(Session* session) : Resource(session) {} |
| |
| Node::Node(Node&& moved) : Resource(std::move(moved)) {} |
| |
| Node::~Node() = default; |
| |
| void Node::SetTranslation(const float translation[3]) { |
| session()->Enqueue(NewSetTranslationCmd(id(), translation)); |
| } |
| |
| void Node::SetTranslation(uint32_t variable_id) { |
| session()->Enqueue(NewSetTranslationCmd(id(), variable_id)); |
| } |
| |
| void Node::SetScale(const float scale[3]) { |
| session()->Enqueue(NewSetScaleCmd(id(), scale)); |
| } |
| |
| void Node::SetScale(uint32_t variable_id) { |
| session()->Enqueue(NewSetScaleCmd(id(), variable_id)); |
| } |
| |
| void Node::SetRotation(const float quaternion[4]) { |
| session()->Enqueue(NewSetRotationCmd(id(), quaternion)); |
| } |
| |
| void Node::SetRotation(uint32_t variable_id) { |
| session()->Enqueue(NewSetRotationCmd(id(), variable_id)); |
| } |
| |
| void Node::SetAnchor(const float anchor[3]) { |
| session()->Enqueue(NewSetAnchorCmd(id(), anchor)); |
| } |
| |
| void Node::SetAnchor(uint32_t variable_id) { |
| session()->Enqueue(NewSetAnchorCmd(id(), variable_id)); |
| } |
| |
| void Node::SendSizeChangeHint(float width_change_factor, |
| float height_change_factor) { |
| session()->Enqueue(NewSendSizeChangeHintCmdHACK(id(), width_change_factor, |
| height_change_factor)); |
| } |
| |
| void Node::SetTag(uint32_t tag_value) { |
| session()->Enqueue(NewSetTagCmd(id(), tag_value)); |
| } |
| |
| void Node::SetHitTestBehavior( |
| fuchsia::ui::gfx::HitTestBehavior hit_test_behavior) { |
| session()->Enqueue(NewSetHitTestBehaviorCmd(id(), hit_test_behavior)); |
| } |
| |
| void Node::Detach() { session()->Enqueue(NewDetachCmd(id())); } |
| |
| ShapeNode::ShapeNode(Session* session) : Node(session) { |
| session->Enqueue(NewCreateShapeNodeCmd(id())); |
| } |
| |
| ShapeNode::ShapeNode(ShapeNode&& moved) : Node(std::move(moved)) {} |
| |
| ShapeNode::~ShapeNode() = default; |
| |
| void ShapeNode::SetShape(uint32_t shape_id) { |
| session()->Enqueue(NewSetShapeCmd(id(), shape_id)); |
| } |
| |
| void ShapeNode::SetMaterial(uint32_t material_id) { |
| session()->Enqueue(NewSetMaterialCmd(id(), material_id)); |
| } |
| |
| ContainerNode::ContainerNode(Session* session) : Node(session) {} |
| |
| ContainerNode::ContainerNode(ContainerNode&& moved) : Node(std::move(moved)) {} |
| |
| ContainerNode::~ContainerNode() = default; |
| |
| void ContainerNode::AddChild(uint32_t child_node_id) { |
| session()->Enqueue(NewAddChildCmd(id(), child_node_id)); |
| } |
| |
| void ContainerNode::AddPart(uint32_t part_node_id) { |
| session()->Enqueue(NewAddPartCmd(id(), part_node_id)); |
| } |
| |
| void ContainerNode::DetachChildren() { |
| session()->Enqueue(NewDetachChildrenCmd(id())); |
| } |
| |
| EntityNode::EntityNode(Session* session) : ContainerNode(session) { |
| session->Enqueue(NewCreateEntityNodeCmd(id())); |
| } |
| |
| void EntityNode::Attach(const ViewHolder& view_holder) { |
| session()->Enqueue(NewAddChildCmd(id(), view_holder.id())); |
| } |
| |
| void EntityNode::Snapshot(fuchsia::ui::gfx::SnapshotCallbackHACKPtr callback) { |
| session()->Enqueue(NewTakeSnapshotCmdHACK(id(), std::move(callback))); |
| } |
| |
| EntityNode::~EntityNode() = default; |
| |
| void EntityNode::SetClip(uint32_t clip_id, bool clip_to_self) { |
| session()->Enqueue(NewSetClipCmd(id(), clip_id, clip_to_self)); |
| } |
| |
| void EntityNode::SetClipPlanes(std::vector<fuchsia::ui::gfx::Plane3> planes) { |
| session()->Enqueue(NewSetClipPlanesCmd(id(), std::move(planes))); |
| } |
| |
| ImportNode::ImportNode(Session* session) : ContainerNode(session) {} |
| |
| ImportNode::ImportNode(ImportNode&& moved) : ContainerNode(std::move(moved)) {} |
| |
| ImportNode::~ImportNode() { |
| ZX_DEBUG_ASSERT_MSG(is_bound_, "Import was never bound."); |
| } |
| |
| void ImportNode::Bind(zx::eventpair import_token) { |
| ZX_DEBUG_ASSERT(!is_bound_); |
| session()->Enqueue(NewImportResourceCmd( |
| id(), fuchsia::ui::gfx::ImportSpec::NODE, std::move(import_token))); |
| is_bound_ = true; |
| } |
| |
| void ImportNode::BindAsRequest(zx::eventpair* out_export_token) { |
| ZX_DEBUG_ASSERT(!is_bound_); |
| session()->Enqueue(NewImportResourceCmdAsRequest( |
| id(), fuchsia::ui::gfx::ImportSpec::NODE, out_export_token)); |
| is_bound_ = true; |
| } |
| |
| void ImportNode::Attach(const ViewHolder& view_holder) { |
| session()->Enqueue(NewAddChildCmd(id(), view_holder.id())); |
| } |
| |
| void ImportNode::Snapshot(fuchsia::ui::gfx::SnapshotCallbackHACKPtr callback) { |
| session()->Enqueue(NewTakeSnapshotCmdHACK(id(), std::move(callback))); |
| } |
| |
| ViewHolder::ViewHolder(Session* session, zx::eventpair token, |
| const std::string& debug_name) |
| : Resource(session) { |
| session->Enqueue(NewCreateViewHolderCmd(id(), std::move(token), debug_name)); |
| } |
| |
| ViewHolder::~ViewHolder() = default; |
| |
| void ViewHolder::SetViewProperties(const float bounding_box_min[3], |
| const float bounding_box_max[3], |
| const float inset_from_min[3], |
| const float inset_from_max[3]) { |
| session()->Enqueue(NewSetViewPropertiesCmd(id(), bounding_box_min, |
| bounding_box_max, inset_from_min, |
| inset_from_max)); |
| } |
| |
| void ViewHolder::SetViewProperties( |
| const fuchsia::ui::gfx::ViewProperties& props) { |
| session()->Enqueue(NewSetViewPropertiesCmd(id(), props)); |
| } |
| |
| View::View(Session* session, zx::eventpair token, const std::string& debug_name) |
| : Resource(session) { |
| session->Enqueue(NewCreateViewCmd(id(), std::move(token), debug_name)); |
| } |
| |
| View::~View() = default; |
| |
| void View::AddChild(const Node& child) const { |
| ZX_DEBUG_ASSERT(session() == child.session()); |
| session()->Enqueue(NewAddChildCmd(id(), child.id())); |
| } |
| |
| void View::DetachChild(const Node& child) const { |
| ZX_DEBUG_ASSERT(session() == child.session()); |
| session()->Enqueue(NewDetachCmd(child.id())); |
| } |
| |
| ClipNode::ClipNode(Session* session) : ContainerNode(session) { |
| session->Enqueue(NewCreateClipNodeCmd(id())); |
| } |
| |
| ClipNode::ClipNode(ClipNode&& moved) : ContainerNode(std::move(moved)) {} |
| |
| ClipNode::~ClipNode() = default; |
| |
| OpacityNode::OpacityNode(Session* session) : ContainerNode(session) { |
| session->Enqueue(NewCreateOpacityNodeCmd(id())); |
| } |
| |
| OpacityNode::OpacityNode(OpacityNode&& moved) |
| : ContainerNode(std::move(moved)) {} |
| |
| OpacityNode::~OpacityNode() = default; |
| |
| void OpacityNode::SetOpacity(float opacity) { |
| opacity = clamp(opacity, 0.f, 1.f); |
| session()->Enqueue(NewSetOpacityCmd(id(), opacity)); |
| } |
| |
| Variable::Variable(Session* session, fuchsia::ui::gfx::Value initial_value) |
| : Resource(session) { |
| session->Enqueue(NewCreateVariableCmd(id(), std::move(initial_value))); |
| } |
| |
| Variable::Variable(Variable&& moved) : Resource(std::move(moved)) {} |
| |
| Variable::~Variable() = default; |
| |
| Scene::Scene(Session* session) : ContainerNode(session) { |
| session->Enqueue(NewCreateSceneCmd(id())); |
| } |
| |
| Scene::Scene(Scene&& moved) : ContainerNode(std::move(moved)) {} |
| |
| Scene::~Scene() = default; |
| |
| void Scene::AddLight(uint32_t light_id) { |
| session()->Enqueue(NewAddLightCmd(id(), light_id)); |
| } |
| |
| void Scene::AddAmbientLight(uint32_t light_id) { |
| session()->Enqueue(NewSceneAddAmbientLightCmd(id(), light_id)); |
| } |
| |
| void Scene::AddDirectionalLight(uint32_t light_id) { |
| session()->Enqueue(NewSceneAddDirectionalLightCmd(id(), light_id)); |
| } |
| |
| void Scene::AddPointLight(uint32_t light_id) { |
| session()->Enqueue(NewSceneAddPointLightCmd(id(), light_id)); |
| } |
| |
| void Scene::DetachLights() { session()->Enqueue(NewDetachLightsCmd(id())); } |
| |
| void CameraBase::SetTransform(const float eye_position[3], |
| const float eye_look_at[3], |
| const float eye_up[3]) { |
| session()->Enqueue( |
| NewSetCameraTransformCmd(id(), eye_position, eye_look_at, eye_up)); |
| } |
| |
| void CameraBase::SetPoseBuffer(const Buffer& buffer, uint32_t num_entries, |
| int64_t base_time, uint64_t time_interval) { |
| session()->Enqueue(NewSetCameraPoseBufferCmd(id(), buffer.id(), num_entries, |
| base_time, time_interval)); |
| } |
| |
| Camera::Camera(const Scene& scene) : Camera(scene.session(), scene.id()) {} |
| |
| Camera::Camera(Session* session, uint32_t scene_id) : CameraBase(session) { |
| session->Enqueue(NewCreateCameraCmd(id(), scene_id)); |
| } |
| |
| Camera::Camera(Camera&& moved) : CameraBase(std::move(moved)) {} |
| |
| Camera::~Camera() = default; |
| |
| void Camera::SetProjection(const float fovy) { |
| session()->Enqueue(NewSetCameraProjectionCmd(id(), fovy)); |
| } |
| |
| StereoCamera::StereoCamera(const Scene& scene) |
| : StereoCamera(scene.session(), scene.id()) {} |
| |
| StereoCamera::StereoCamera(Session* session, uint32_t scene_id) |
| : CameraBase(session) { |
| session->Enqueue(NewCreateStereoCameraCmd(id(), scene_id)); |
| } |
| |
| StereoCamera::StereoCamera(StereoCamera&& moved) |
| : CameraBase(std::move(moved)) {} |
| |
| StereoCamera::~StereoCamera() = default; |
| |
| void StereoCamera::SetStereoProjection(const float left_projection[16], |
| const float right_projection[16]) { |
| session()->Enqueue( |
| NewSetStereoCameraProjectionCmd(id(), left_projection, right_projection)); |
| } |
| |
| Renderer::Renderer(Session* session) : Resource(session) { |
| session->Enqueue(NewCreateRendererCmd(id())); |
| } |
| |
| Renderer::Renderer(Renderer&& moved) : Resource(std::move(moved)) {} |
| |
| Renderer::~Renderer() = default; |
| |
| void Renderer::SetCamera(uint32_t camera_id) { |
| session()->Enqueue(NewSetCameraCmd(id(), camera_id)); |
| } |
| |
| void Renderer::SetParam(fuchsia::ui::gfx::RendererParam param) { |
| session()->Enqueue(NewSetRendererParamCmd(id(), std::move(param))); |
| } |
| |
| void Renderer::SetShadowTechnique(fuchsia::ui::gfx::ShadowTechnique technique) { |
| auto param = fuchsia::ui::gfx::RendererParam(); |
| param.set_shadow_technique(technique); |
| SetParam(std::move(param)); |
| } |
| |
| void Renderer::SetDisableClipping(bool disable_clipping) { |
| session()->Enqueue(NewSetDisableClippingCmd(id(), disable_clipping)); |
| } |
| |
| void Renderer::SetEnableDebugging(bool enable_debugging) { |
| auto param = fuchsia::ui::gfx::RendererParam(); |
| param.set_enable_debugging(enable_debugging); |
| SetParam(std::move(param)); |
| } |
| |
| Layer::Layer(Session* session) : Resource(session) { |
| session->Enqueue(NewCreateLayerCmd(id())); |
| } |
| |
| Layer::Layer(Layer&& moved) : Resource(std::move(moved)) {} |
| |
| Layer::~Layer() = default; |
| |
| void Layer::SetRenderer(uint32_t renderer_id) { |
| session()->Enqueue(NewSetRendererCmd(id(), renderer_id)); |
| } |
| |
| void Layer::SetSize(const float size[2]) { |
| session()->Enqueue(NewSetSizeCmd(id(), size)); |
| } |
| |
| LayerStack::LayerStack(Session* session) : Resource(session) { |
| session->Enqueue(NewCreateLayerStackCmd(id())); |
| } |
| |
| LayerStack::LayerStack(LayerStack&& moved) : Resource(std::move(moved)) {} |
| |
| LayerStack::~LayerStack() = default; |
| |
| void LayerStack::AddLayer(uint32_t layer_id) { |
| session()->Enqueue(NewAddLayerCmd(id(), layer_id)); |
| } |
| |
| void LayerStack::RemoveLayer(uint32_t layer_id) { |
| session()->Enqueue(NewRemoveLayerCmd(id(), layer_id)); |
| } |
| |
| void LayerStack::RemoveAllLayers() { |
| session()->Enqueue(NewRemoveAllLayersCmd(id())); |
| } |
| |
| DisplayCompositor::DisplayCompositor(Session* session) : Resource(session) { |
| session->Enqueue(NewCreateDisplayCompositorCmd(id())); |
| } |
| |
| DisplayCompositor::DisplayCompositor(DisplayCompositor&& moved) |
| : Resource(std::move(moved)) {} |
| |
| DisplayCompositor::~DisplayCompositor() = default; |
| |
| void DisplayCompositor::SetLayerStack(uint32_t layer_stack_id) { |
| session()->Enqueue(NewSetLayerStackCmd(id(), layer_stack_id)); |
| } |
| |
| Compositor::Compositor(Session* session) : Resource(session) { |
| session->Enqueue(NewCreateCompositorCmd(id())); |
| } |
| |
| Compositor::Compositor(Compositor&& moved) : Resource(std::move(moved)) {} |
| |
| Compositor::~Compositor() = default; |
| |
| void Compositor::SetLayerStack(uint32_t layer_stack_id) { |
| session()->Enqueue(NewSetLayerStackCmd(id(), layer_stack_id)); |
| } |
| |
| Light::Light(Session* session) : Resource(session) {} |
| |
| Light::Light(Light&& moved) : Resource(std::move(moved)) {} |
| |
| Light::~Light() = default; |
| |
| void Light::SetColor(const float rgb[3]) { |
| session()->Enqueue(NewSetLightColorCmd(id(), rgb)); |
| } |
| |
| void Light::SetColor(uint32_t variable_id) { |
| session()->Enqueue(NewSetLightColorCmd(id(), variable_id)); |
| } |
| |
| void Light::Detach() { session()->Enqueue(NewDetachLightCmd(id())); } |
| |
| AmbientLight::AmbientLight(Session* session) : Light(session) { |
| session->Enqueue(NewCreateAmbientLightCmd(id())); |
| } |
| |
| AmbientLight::AmbientLight(AmbientLight&& moved) : Light(std::move(moved)) {} |
| |
| AmbientLight::~AmbientLight() = default; |
| |
| DirectionalLight::DirectionalLight(Session* session) : Light(session) { |
| session->Enqueue(NewCreateDirectionalLightCmd(id())); |
| } |
| |
| DirectionalLight::DirectionalLight(DirectionalLight&& moved) |
| : Light(std::move(moved)) {} |
| |
| DirectionalLight::~DirectionalLight() = default; |
| |
| void DirectionalLight::SetDirection(const float direction[3]) { |
| session()->Enqueue(NewSetLightDirectionCmd(id(), direction)); |
| } |
| |
| void DirectionalLight::SetDirection(uint32_t variable_id) { |
| session()->Enqueue(NewSetLightDirectionCmd(id(), variable_id)); |
| } |
| |
| PointLight::PointLight(Session* session) : Light(session) { |
| session->Enqueue(NewCreatePointLightCmd(id())); |
| } |
| |
| PointLight::PointLight(PointLight&& moved) : Light(std::move(moved)) {} |
| |
| PointLight::~PointLight() = default; |
| |
| void PointLight::SetPosition(const float position[3]) { |
| session()->Enqueue(NewSetPointLightPositionCmd(id(), position)); |
| } |
| |
| void PointLight::SetPosition(uint32_t variable_id) { |
| session()->Enqueue(NewSetPointLightPositionCmd(id(), variable_id)); |
| } |
| |
| void PointLight::SetFalloff(float falloff) { |
| session()->Enqueue(NewSetPointLightFalloffCmd(id(), falloff)); |
| } |
| |
| } // namespace scenic |