blob: b4ab859baf51e1ceab593d6ce2031bd6e7571045 [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.
#include <lib/images/cpp/images.h>
#include <lib/ui/scenic/cpp/commands.h>
#include <lib/ui/scenic/cpp/resources.h>
#include <lib/ui/scenic/cpp/view_token_pair.h>
#include <algorithm>
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) noexcept : 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) noexcept : Resource(std::move(moved)) {}
Shape::~Shape() = default;
Circle::Circle(Session* session, float radius) : Shape(session) {
session->Enqueue(NewCreateCircleCmd(id(), radius));
}
Circle::Circle(Circle&& moved) noexcept : 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) noexcept : 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) noexcept : 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, 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_, info));
}
Image::Image(Image&& moved) noexcept
: 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) noexcept : 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) noexcept
: 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) noexcept : 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 std::array<float, 3>& bounding_box_min,
const std::array<float, 3>& bounding_box_max) {
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(),
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) noexcept : 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) noexcept : Resource(std::move(moved)) {}
Node::~Node() = default;
void Node::SetTranslation(const std::array<float, 3>& translation) {
session()->Enqueue(NewSetTranslationCmd(id(), translation));
}
void Node::SetTranslation(uint32_t variable_id) {
session()->Enqueue(NewSetTranslationCmd(id(), variable_id));
}
void Node::SetScale(const std::array<float, 3>& scale) {
session()->Enqueue(NewSetScaleCmd(id(), scale));
}
void Node::SetScale(uint32_t variable_id) { session()->Enqueue(NewSetScaleCmd(id(), variable_id)); }
void Node::SetRotation(const std::array<float, 4>& quaternion) {
session()->Enqueue(NewSetRotationCmd(id(), quaternion));
}
void Node::SetRotation(uint32_t variable_id) {
session()->Enqueue(NewSetRotationCmd(id(), variable_id));
}
void Node::SetAnchor(const std::array<float, 3>& anchor) {
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) noexcept : 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) noexcept : Node(std::move(moved)) {}
ContainerNode::~ContainerNode() = default;
void ContainerNode::AddChild(uint32_t child_node_id) {
session()->Enqueue(NewAddChildCmd(id(), child_node_id));
}
void ContainerNode::DetachChildren() { session()->Enqueue(NewDetachChildrenCmd(id())); }
EntityNode::EntityNode(Session* session) : ContainerNode(session) {
session->Enqueue(NewCreateEntityNodeCmd(id()));
}
EntityNode::EntityNode(EntityNode&& moved) noexcept : ContainerNode(std::move(moved)) {}
EntityNode::~EntityNode() = default;
void EntityNode::Attach(const ViewHolder& view_holder) { AddChild(view_holder); }
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) noexcept : 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()));
}
ViewHolder::ViewHolder(Session* session, zx::eventpair token, const std::string& debug_name)
: Node(session) {
session->Enqueue(
NewCreateViewHolderCmd(id(), scenic::ToViewHolderToken(std::move(token)), debug_name));
}
ViewHolder::ViewHolder(Session* session, fuchsia::ui::views::ViewHolderToken token,
const std::string& debug_name)
: Node(session) {
session->Enqueue(NewCreateViewHolderCmd(id(), std::move(token), debug_name));
}
ViewHolder::ViewHolder(ViewHolder&& moved) noexcept : Node(std::move(moved)) {}
ViewHolder::~ViewHolder() = default;
void ViewHolder::SetViewProperties(const std::array<float, 3>& bounding_box_min,
const std::array<float, 3>& bounding_box_max,
const std::array<float, 3>& inset_from_min,
const std::array<float, 3>& inset_from_max) {
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));
}
void ViewHolder::SetDebugBoundsColor(uint8_t red, uint8_t green, uint8_t blue) {
session()->Enqueue(NewSetViewHolderBoundsColorCmd(id(), red, green, blue));
}
View::View(Session* session, zx::eventpair token, const std::string& debug_name)
: Resource(session) {
session->Enqueue(NewCreateViewCmd(id(), scenic::ToViewToken(std::move(token)), debug_name));
}
View::View(Session* session, fuchsia::ui::views::ViewToken token, const std::string& debug_name)
: Resource(session) {
session->Enqueue(NewCreateViewCmd(id(), std::move(token), debug_name));
}
View::View(Session* session, fuchsia::ui::views::ViewToken token,
fuchsia::ui::views::ViewRefControl control_ref, fuchsia::ui::views::ViewRef view_ref,
const std::string& debug_name)
: Resource(session) {
session->Enqueue(NewCreateViewCmd(id(), std::move(token), std::move(control_ref),
std::move(view_ref), debug_name));
}
View::View(View&& moved) noexcept : Resource(std::move(moved)) {}
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()));
}
void View::enableDebugBounds(bool enable) {
session()->Enqueue(NewSetEnableDebugViewBoundsCmd(id(), enable));
}
ClipNode::ClipNode(Session* session) : ContainerNode(session) {
session->Enqueue(NewCreateClipNodeCmd(id()));
}
ClipNode::ClipNode(ClipNode&& moved) noexcept : ContainerNode(std::move(moved)) {}
ClipNode::~ClipNode() = default;
OpacityNodeHACK::OpacityNodeHACK(Session* session) : ContainerNode(session) {
session->Enqueue(NewCreateOpacityNodeCmdHACK(id()));
}
OpacityNodeHACK::OpacityNodeHACK(OpacityNodeHACK&& moved) noexcept
: ContainerNode(std::move(moved)) {}
OpacityNodeHACK::~OpacityNodeHACK() = default;
void OpacityNodeHACK::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) noexcept : Resource(std::move(moved)) {}
Variable::~Variable() = default;
Scene::Scene(Session* session) : ContainerNode(session) {
session->Enqueue(NewCreateSceneCmd(id()));
}
Scene::Scene(Scene&& moved) noexcept : 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 std::array<float, 3>& eye_position,
const std::array<float, 3>& eye_look_at,
const std::array<float, 3>& eye_up) {
session()->Enqueue(NewSetCameraTransformCmd(id(), eye_position, eye_look_at, eye_up));
}
void CameraBase::SetClipSpaceTransform(float x, float y, float scale) {
session()->Enqueue(NewSetCameraClipSpaceTransformCmd(id(), x, y, scale));
}
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));
}
void CameraBase::SetPoseBuffer(const Buffer& buffer, uint32_t num_entries, zx::time base_time,
zx::duration time_interval) {
SetPoseBuffer(buffer, num_entries, base_time.get(), time_interval.get());
}
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) noexcept : 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) noexcept : CameraBase(std::move(moved)) {}
StereoCamera::~StereoCamera() = default;
void StereoCamera::SetStereoProjection(const std::array<float, 4 * 4>& left_projection,
const std::array<float, 4 * 4>& right_projection) {
session()->Enqueue(NewSetStereoCameraProjectionCmd(id(), left_projection, right_projection));
}
Renderer::Renderer(Session* session) : Resource(session) {
session->Enqueue(NewCreateRendererCmd(id()));
}
Renderer::Renderer(Renderer&& moved) noexcept : 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) noexcept : Resource(std::move(moved)) {}
Layer::~Layer() = default;
void Layer::SetRenderer(uint32_t renderer_id) {
session()->Enqueue(NewSetRendererCmd(id(), renderer_id));
}
void Layer::SetSize(const std::array<float, 2>& size) {
session()->Enqueue(NewSetSizeCmd(id(), size));
}
LayerStack::LayerStack(Session* session) : Resource(session) {
session->Enqueue(NewCreateLayerStackCmd(id()));
}
LayerStack::LayerStack(LayerStack&& moved) noexcept : 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) noexcept
: Resource(std::move(moved)) {}
DisplayCompositor::~DisplayCompositor() = default;
void DisplayCompositor::SetLayerStack(uint32_t layer_stack_id) {
session()->Enqueue(NewSetLayerStackCmd(id(), layer_stack_id));
}
void DisplayCompositor::SetColorConversion(const std::array<float, 3>& preoffsets,
const std::array<float, 3 * 3>& matrix,
const std::array<float, 3>& postoffsets) {
session()->Enqueue(NewSetDisplayColorConversionCmdHACK(id(), preoffsets, matrix, postoffsets));
}
void DisplayCompositor::SetLayoutRotation(uint32_t rotation_degrees) {
session()->Enqueue(NewSetDisplayRotationCmdHACK(id(), rotation_degrees));
}
Compositor::Compositor(Session* session) : Resource(session) {
session->Enqueue(NewCreateCompositorCmd(id()));
}
Compositor::Compositor(Compositor&& moved) noexcept : Resource(std::move(moved)) {}
Compositor::~Compositor() = default;
void Compositor::SetLayerStack(uint32_t layer_stack_id) {
session()->Enqueue(NewSetLayerStackCmd(id(), layer_stack_id));
}
void Compositor::SetLayoutRotation(uint32_t rotation_degrees) {
session()->Enqueue(NewSetDisplayRotationCmdHACK(id(), rotation_degrees));
}
Light::Light(Session* session) : Resource(session) {}
Light::Light(Light&& moved) noexcept : Resource(std::move(moved)) {}
Light::~Light() = default;
void Light::SetColor(const std::array<float, 3>& rgb) {
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) noexcept : Light(std::move(moved)) {}
AmbientLight::~AmbientLight() = default;
DirectionalLight::DirectionalLight(Session* session) : Light(session) {
session->Enqueue(NewCreateDirectionalLightCmd(id()));
}
DirectionalLight::DirectionalLight(DirectionalLight&& moved) noexcept : Light(std::move(moved)) {}
DirectionalLight::~DirectionalLight() = default;
void DirectionalLight::SetDirection(const std::array<float, 3>& direction) {
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) noexcept : Light(std::move(moved)) {}
PointLight::~PointLight() = default;
void PointLight::SetPosition(const std::array<float, 3>& position) {
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