blob: 57807c3833f62a0fb2e8325ddd7442d888604089 [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.
#include "src/camera/examples/video_display/simple_camera_view.h"
// clang-format off
#include "src/ui/lib/glm_workaround/glm_workaround.h"
// clang-format on
#include <lib/ui/scenic/cpp/commands.h>
#include <glm/gtc/type_ptr.hpp>
#include <src/lib/fxl/log_level.h>
namespace video_display {
namespace {
constexpr uint32_t kShapeWidth = 640;
constexpr uint32_t kShapeHeight = 480;
constexpr float kDisplayHeight = 50;
constexpr float kInitialWindowXPos = 320;
constexpr float kInitialWindowYPos = 240;
} // namespace
static const std::string kSimpleCameraServiceUrl =
"fuchsia-pkg://fuchsia.com/simple_camera_server_cpp#meta/"
"simple_camera_server_cpp.cmx";
static const bool camera_id = 0; // 0 -> real camera, 1 -> fake
SimpleCameraView::SimpleCameraView(scenic::ViewContext view_context)
: BaseView(std::move(view_context), "Video Display Example"),
node_(session()) {
FXL_VLOG(4) << "Creating video_display View";
// Create an ImagePipe and pass one end to the Session:
fidl::InterfaceHandle<fuchsia::images::ImagePipe> image_pipe_handle;
uint32_t image_pipe_id = session()->AllocResourceId();
session()->Enqueue(scenic::NewCreateImagePipeCmd(
image_pipe_id, image_pipe_handle.NewRequest()));
// Create a material that has our image pipe mapped onto it:
scenic::Material material(session());
material.SetTexture(image_pipe_id);
session()->ReleaseResource(image_pipe_id);
// Connect to the simple camera service:
fuchsia::sys::LaunchInfo launch_info;
launch_info.url = kSimpleCameraServiceUrl;
launch_info.directory_request = simple_camera_provider_.NewRequest();
startup_context()->launcher()->CreateComponent(std::move(launch_info),
controller_.NewRequest());
simple_camera_provider_.ConnectToService(
simple_camera_.NewRequest().TakeChannel(),
fuchsia::simplecamera::SimpleCamera::Name_);
// Now pass the other end of the image pipe to the simple camera interface:
simple_camera_->ConnectToCamera(camera_id, std::move(image_pipe_handle));
simple_camera_.set_error_handler([](zx_status_t error) {
if (error) {
FXL_PLOG(FATAL, error) << "Camera connection failed";
}
});
// Create a rounded-rect shape to display the camera image on.
scenic::RoundedRectangle shape(session(), kShapeWidth, kShapeHeight, 80, 80,
80, 80);
node_.SetShape(shape);
node_.SetMaterial(material);
root_node().AddChild(node_);
// Translation of 0, 0 is the middle of the screen
node_.SetTranslation(kInitialWindowXPos, kInitialWindowYPos, -kDisplayHeight);
InvalidateScene();
}
void SimpleCameraView::OnSceneInvalidated(
fuchsia::images::PresentationInfo presentation_info) {
if (!has_logical_size()) {
return;
}
// Compute the amount of time that has elapsed since the view was created.
double seconds =
static_cast<double>(presentation_info.presentation_time) / 1'000'000'000;
const float kHalfWidth = logical_size().x * 0.5f;
const float kHalfHeight = logical_size().y * 0.5f;
// Compute the translation for the window to swirl around the screen.
// Why do this? Well, this is an example of what a View can do, and it helps
// debug the camera to know if scenic is still running.
node_.SetTranslation(kHalfWidth * (1. + .1 * sin(seconds * 0.8)),
kHalfHeight * (1. + .1 * sin(seconds * 0.6)),
-kDisplayHeight);
// The rounded-rectangles are constantly animating; invoke InvalidateScene()
// to guarantee that OnSceneInvalidated() will be called again.
InvalidateScene();
}
} // namespace video_display