blob: c29bc82cc3e2a07219bd8dc553cc8ed4b5791573 [file] [log] [blame]
// Copyright 2018 The Chromium 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 "ui/ozone/platform/scenic/scenic_session.h"
#include "base/fuchsia/fuchsia_logging.h"
namespace ui {
namespace {
// Max number of commands that will fit in a single message.
//
// TODO(sergeyu): Improve this logic when FIDL provides a mechanism to estimate
// message size, see https://fuchsia.atlassian.net/browse/FIDL-212 .
constexpr size_t kCommandsPerMessage =
std::max(static_cast<size_t>(ZX_CHANNEL_MAX_MSG_HANDLES),
(ZX_CHANNEL_MAX_MSG_BYTES - sizeof(fidl_message_header_t) -
sizeof(fidl_vector_t)) /
sizeof(fuchsia::ui::gfx::Command));
// Helper function for all resource creation functions.
fuchsia::ui::gfx::Command NewCreateResourceCommand(
ScenicSession::ResourceId resource_id,
fuchsia::ui::gfx::ResourceArgs resource) {
fuchsia::ui::gfx::CreateResourceCmd create_resource;
create_resource.id = resource_id;
create_resource.resource = std::move(resource);
fuchsia::ui::gfx::Command command;
command.set_create_resource(std::move(create_resource));
return command;
}
fuchsia::ui::gfx::Command NewReleaseResourceCommand(
ScenicSession::ResourceId resource_id) {
fuchsia::ui::gfx::ReleaseResourceCmd release_resource;
release_resource.id = resource_id;
fuchsia::ui::gfx::Command command;
command.set_release_resource(std::move(release_resource));
return command;
}
} // namespace
ScenicSession::ScenicSession(fuchsia::ui::scenic::Scenic* scenic,
ScenicSessionListener* listener)
: listener_(listener), session_listener_binding_(this) {
scenic->CreateSession(session_.NewRequest(),
session_listener_binding_.NewBinding());
session_.set_error_handler([this]() {
Close();
listener_->OnScenicError("ScenicSession disconnected unexpectedly.");
});
}
ScenicSession::~ScenicSession() {
DCHECK_EQ(resource_count_, 0);
}
void ScenicSession::ReleaseResource(ResourceId resource_id) {
resource_count_--;
EnqueueGfxCommand(NewReleaseResourceCommand(resource_id));
}
ScenicSession::ResourceId ScenicSession::CreateMemory(
base::SharedMemoryHandle vmo,
fuchsia::images::MemoryType memory_type) {
DCHECK(vmo.IsValid());
fuchsia::ui::gfx::MemoryArgs memory;
memory.vmo = zx::vmo(vmo.GetHandle());
memory.memory_type = memory_type;
fuchsia::ui::gfx::ResourceArgs resource;
resource.set_memory(std::move(memory));
ResourceId memory_id = AllocateResourceId();
EnqueueGfxCommand(NewCreateResourceCommand(memory_id, std::move(resource)));
return memory_id;
}
ScenicSession::ResourceId ScenicSession::CreateImage(
ResourceId memory_id,
ResourceId memory_offset,
fuchsia::images::ImageInfo info) {
fuchsia::ui::gfx::ImageArgs image;
image.memory_id = memory_id;
image.memory_offset = memory_offset;
image.info = std::move(info);
fuchsia::ui::gfx::ResourceArgs resource;
resource.set_image(std::move(image));
ResourceId image_id = AllocateResourceId();
EnqueueGfxCommand(NewCreateResourceCommand(image_id, std::move(resource)));
return image_id;
}
ScenicSession::ResourceId ScenicSession::CreateImagePipe(
fidl::InterfaceRequest<fuchsia::images::ImagePipe> request) {
fuchsia::ui::gfx::ImagePipeArgs image_pipe;
image_pipe.image_pipe_request = std::move(request);
fuchsia::ui::gfx::ResourceArgs resource;
resource.set_image_pipe(std::move(image_pipe));
ResourceId image_pipe_id = AllocateResourceId();
EnqueueGfxCommand(
NewCreateResourceCommand(image_pipe_id, std::move(resource)));
return image_pipe_id;
}
ScenicSession::ResourceId ScenicSession::ImportResource(
fuchsia::ui::gfx::ImportSpec spec,
zx::eventpair import_token) {
DCHECK(import_token);
ResourceId resource_id = AllocateResourceId();
fuchsia::ui::gfx::ImportResourceCmd import_resource;
import_resource.id = resource_id;
import_resource.token = std::move(import_token);
import_resource.spec = spec;
fuchsia::ui::gfx::Command command;
command.set_import_resource(std::move(import_resource));
EnqueueGfxCommand(std::move(command));
return resource_id;
}
ScenicSession::ResourceId ScenicSession::CreateEntityNode() {
fuchsia::ui::gfx::ResourceArgs resource;
resource.set_entity_node(fuchsia::ui::gfx::EntityNodeArgs());
ResourceId node_id = AllocateResourceId();
EnqueueGfxCommand(NewCreateResourceCommand(node_id, std::move(resource)));
return node_id;
}
ScenicSession::ResourceId ScenicSession::CreateShapeNode() {
fuchsia::ui::gfx::ResourceArgs resource;
resource.set_shape_node(fuchsia::ui::gfx::ShapeNodeArgs());
ResourceId node_id = AllocateResourceId();
EnqueueGfxCommand(NewCreateResourceCommand(node_id, std::move(resource)));
return node_id;
}
void ScenicSession::AddNodeChild(ResourceId node_id, ResourceId child_id) {
fuchsia::ui::gfx::AddChildCmd add_child;
add_child.node_id = node_id;
add_child.child_id = child_id;
fuchsia::ui::gfx::Command command;
command.set_add_child(std::move(add_child));
EnqueueGfxCommand(std::move(command));
}
void ScenicSession::SetNodeTranslation(ResourceId node_id,
const float translation[3]) {
fuchsia::ui::gfx::SetTranslationCmd set_translation;
set_translation.id = node_id;
set_translation.value.variable_id = 0;
set_translation.value.value.x = translation[0];
set_translation.value.value.y = translation[1];
set_translation.value.value.z = translation[2];
fuchsia::ui::gfx::Command command;
command.set_set_translation(std::move(set_translation));
EnqueueGfxCommand(std::move(command));
}
ScenicSession::ResourceId ScenicSession::CreateRectangle(float width,
float height) {
fuchsia::ui::gfx::Value width_value;
width_value.set_vector1(width);
fuchsia::ui::gfx::Value height_value;
height_value.set_vector1(height);
fuchsia::ui::gfx::RectangleArgs rectangle;
rectangle.width = std::move(width_value);
rectangle.height = std::move(height_value);
fuchsia::ui::gfx::ResourceArgs resource;
resource.set_rectangle(std::move(rectangle));
ResourceId rectangle_id = AllocateResourceId();
EnqueueGfxCommand(
NewCreateResourceCommand(rectangle_id, std::move(resource)));
return rectangle_id;
}
ScenicSession::ResourceId ScenicSession::CreateMaterial() {
fuchsia::ui::gfx::ResourceArgs resource;
resource.set_material(fuchsia::ui::gfx::MaterialArgs());
ResourceId material_id = AllocateResourceId();
EnqueueGfxCommand(NewCreateResourceCommand(material_id, std::move(resource)));
return material_id;
}
void ScenicSession::SetNodeMaterial(ResourceId node_id,
ResourceId material_id) {
fuchsia::ui::gfx::SetMaterialCmd set_material;
set_material.node_id = node_id;
set_material.material_id = material_id;
fuchsia::ui::gfx::Command command;
command.set_set_material(std::move(set_material));
EnqueueGfxCommand(std::move(command));
}
void ScenicSession::SetNodeShape(ResourceId node_id, ResourceId shape_id) {
fuchsia::ui::gfx::SetShapeCmd set_shape;
set_shape.node_id = node_id;
set_shape.shape_id = shape_id;
fuchsia::ui::gfx::Command command;
command.set_set_shape(std::move(set_shape));
EnqueueGfxCommand(std::move(command));
}
void ScenicSession::SetMaterialTexture(ResourceId material_id,
ResourceId texture_id) {
fuchsia::ui::gfx::SetTextureCmd set_texture;
set_texture.material_id = material_id;
set_texture.texture_id = texture_id;
fuchsia::ui::gfx::Command command;
command.set_set_texture(std::move(set_texture));
EnqueueGfxCommand(std::move(command));
}
void ScenicSession::SetEventMask(ResourceId resource_id, uint32_t event_mask) {
fuchsia::ui::gfx::SetEventMaskCmd set_event_mask;
set_event_mask.id = resource_id;
set_event_mask.event_mask = event_mask;
fuchsia::ui::gfx::Command command;
command.set_set_event_mask(std::move(set_event_mask));
EnqueueGfxCommand(std::move(command));
}
void ScenicSession::AddAcquireFence(zx::event fence) {
acquire_fences_.push_back(std::move(fence));
}
void ScenicSession::AddReleaseFence(zx::event fence) {
release_fences_.push_back(std::move(fence));
}
void ScenicSession::Present() {
Flush();
session_->Present(/*flags=*/0,
fidl::VectorPtr<zx::event>(std::move(acquire_fences_)),
fidl::VectorPtr<zx::event>(std::move(release_fences_)),
[](fuchsia::images::PresentationInfo info) {});
}
void ScenicSession::Close() {
session_.set_error_handler(nullptr);
session_.Unbind();
session_listener_binding_.Unbind();
}
void ScenicSession::OnScenicError(fidl::StringPtr error) {
Close();
listener_->OnScenicError(error);
}
void ScenicSession::OnScenicEvent(
fidl::VectorPtr<fuchsia::ui::scenic::Event> events) {
listener_->OnScenicEvents(events.get());
}
ScenicSession::ResourceId ScenicSession::AllocateResourceId() {
resource_count_++;
return next_resource_id_++;
}
void ScenicSession::EnqueueGfxCommand(fuchsia::ui::gfx::Command command) {
fuchsia::ui::scenic::Command scenic_command;
scenic_command.set_gfx(std::move(command));
queued_commands_.push_back(std::move(scenic_command));
DCHECK_LE(queued_commands_->size(), kCommandsPerMessage);
if (queued_commands_->size() == kCommandsPerMessage)
Flush();
}
void ScenicSession::Flush() {
if (!queued_commands_->empty())
session_->Enqueue(std::move(queued_commands_));
}
} // namespace ui