Commit d239fd5a authored by Sergey Ulanov's avatar Sergey Ulanov Committed by Commit Bot

[Fuchsia] Use scenic_cpp in Ozone

Previously scenic platform was using FIDL Scenic interfaces directly.
SDK now includes scenic_cpp wrappers for Scenic interfaces. This CL
updates Scenic Ozone platform to use scenic_cpp, which makes the code
more readable and less error-prone.

Bug: 899348
Change-Id: Id5fac3485b6a8cfac1aaefe1a921555090ec8138
Reviewed-on: https://chromium-review.googlesource.com/c/1308987
Commit-Queue: Sergey Ulanov <sergeyu@chromium.org>
Reviewed-by: default avatarWez <wez@chromium.org>
Cr-Commit-Position: refs/heads/master@{#604102}
parent 5d014c91
......@@ -16,8 +16,6 @@ source_set("scenic") {
"ozone_platform_scenic.h",
"scenic_screen.cc",
"scenic_screen.h",
"scenic_session.cc",
"scenic_session.h",
"scenic_surface_factory.cc",
"scenic_surface_factory.h",
"scenic_window.cc",
......@@ -37,6 +35,7 @@ source_set("scenic") {
"//third_party/fuchsia-sdk/sdk:images",
"//third_party/fuchsia-sdk/sdk:mem",
"//third_party/fuchsia-sdk/sdk:scenic",
"//third_party/fuchsia-sdk/sdk:scenic_cpp",
"//third_party/fuchsia-sdk/sdk:viewsv1",
"//third_party/fuchsia-sdk/sdk:viewsv1token",
"//ui/base",
......
// 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,
uint64_t allocation_size) {
DCHECK(vmo.IsValid());
fuchsia::ui::gfx::MemoryArgs memory;
memory.vmo = zx::vmo(vmo.GetHandle());
memory.memory_type = memory_type;
memory.allocation_size = allocation_size;
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
// 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.
#ifndef UI_OZONE_PLATFORM_SCENIC_SCENIC_SESSION_H_
#define UI_OZONE_PLATFORM_SCENIC_SCENIC_SESSION_H_
#include <string>
#include <vector>
#include <fuchsia/ui/gfx/cpp/fidl.h>
#include <fuchsia/ui/scenic/cpp/fidl.h>
#include <lib/fidl/cpp/binding.h>
#include <lib/zx/event.h>
#include <lib/zx/eventpair.h>
#include "base/macros.h"
#include "base/memory/shared_memory_handle.h"
namespace ui {
// Interface used to receive events and error notifications from ScenicSession.
class ScenicSessionListener {
public:
ScenicSessionListener() = default;
virtual void OnScenicError(const std::string& error) = 0;
virtual void OnScenicEvents(
const std::vector<fuchsia::ui::scenic::Event>& events) = 0;
protected:
virtual ~ScenicSessionListener() = default;
DISALLOW_COPY_AND_ASSIGN(ScenicSessionListener);
};
// ScenicSession represents a session used to interact with Scenic. It sends
// commands to Scenic via fuchsia::ui::scenic::Session interface. ScenicWindow
// creates a separate session for each window.
class ScenicSession : public fuchsia::ui::scenic::SessionListener {
public:
using ResourceId = uint32_t;
// Creates and wraps a new session for |scenic_service|. |listener| must
// outlive ScenicSession.
ScenicSession(fuchsia::ui::scenic::Scenic* scenic_service,
ScenicSessionListener* listener);
~ScenicSession() override;
// Following functions enqueue various Scenic commands. See
// https://fuchsia.googlesource.com/garnet/+/master/public/lib/ui/gfx/fidl/commands.fidl
// for descriptions of the commands and the fields. Create*() methods return
// ID of the created resource. Resource IDs are only valid within context of
// the session.
void ReleaseResource(ResourceId resource_id);
ResourceId CreateMemory(base::SharedMemoryHandle vmo,
fuchsia::images::MemoryType memory_type,
uint64_t allocation_size);
ResourceId CreateImage(ResourceId memory_id,
ResourceId memory_offset,
fuchsia::images::ImageInfo info);
ResourceId CreateImagePipe(
fidl::InterfaceRequest<fuchsia::images::ImagePipe> request);
ResourceId ImportResource(fuchsia::ui::gfx::ImportSpec spec,
zx::eventpair import_token);
ResourceId CreateEntityNode();
ResourceId CreateShapeNode();
void AddNodeChild(ResourceId node_id, ResourceId child_id);
void SetNodeTranslation(ResourceId node_id, const float translation[3]);
ResourceId CreateRectangle(float width, float height);
ResourceId CreateMaterial();
void SetNodeMaterial(ResourceId node_id, ResourceId material_id);
void SetNodeShape(ResourceId node_id, ResourceId shape_id);
void SetMaterialTexture(ResourceId material_id, ResourceId texture_id);
void SetEventMask(ResourceId resource_id, uint32_t event_mask);
// Enqueue acquire or release fences for the next Present() call. See
// Scenic documentation for description on how these should be used:
// https://fuchsia.googlesource.com/garnet/+/master/public/lib/ui/scenic/fidl/session.fidl
void AddAcquireFence(zx::event fence);
void AddReleaseFence(zx::event fence);
// Flushes queued commands and presents the resulting frame.
void Present();
private:
// fuchsia::ui::scenic::SessionListener interface.
void OnScenicError(fidl::StringPtr error) override;
void OnScenicEvent(
fidl::VectorPtr<fuchsia::ui::scenic::Event> events) override;
// Allocates a new unique resource id.
ResourceId AllocateResourceId();
// Enqueues a scenic |command|.
void EnqueueGfxCommand(fuchsia::ui::gfx::Command command);
// Flushes |queued_commands_|.
void Flush();
// Unbinds |session_| and |session_listener_binding_|, which frees the
// resources used for the session in Scenic and guarantees that we wont
// receive SessionListener events.
void Close();
ScenicSessionListener* const listener_;
fuchsia::ui::scenic::SessionPtr session_;
fidl::Binding<fuchsia::ui::scenic::SessionListener> session_listener_binding_;
ResourceId next_resource_id_ = 1u;
// Used to verify that all resources are freed when the session is closed.
int resource_count_ = 0u;
fidl::VectorPtr<fuchsia::ui::scenic::Command> queued_commands_;
// Pending acquire and release fences passed in the next Present() call.
std::vector<zx::event> acquire_fences_;
std::vector<zx::event> release_fences_;
DISALLOW_COPY_AND_ASSIGN(ScenicSession);
};
} // namespace ui
#endif // UI_OZONE_PLATFORM_SCENIC_SCENIC_SESSION_H_
......@@ -32,28 +32,29 @@ ScenicWindow::ScenicWindow(
window_id_(manager_->AddWindow(this)),
event_dispatcher_(this),
view_listener_binding_(this),
scenic_session_(manager_->GetScenic(), this),
scenic_session_(manager_->GetScenic()),
parent_node_(&scenic_session_),
node_(&scenic_session_),
shape_node_(&scenic_session_),
material_(&scenic_session_),
input_listener_binding_(this) {
// Create event pair to import parent view node to Scenic. One end is passed
// directly to Scenic in ImportResource command and the second one is passed
// to ViewManager::CreateView(). ViewManager will passes it to Scenic when the
// view is added to a container.
scenic_session_.set_error_handler(
fit::bind_member(this, &ScenicWindow::OnScenicError));
scenic_session_.set_event_handler(
fit::bind_member(this, &ScenicWindow::OnScenicEvents));
// Import parent node and create event pair to pass to the ViewManager.
zx::eventpair parent_export_token;
zx::eventpair parent_import_token;
zx_status_t status =
zx::eventpair::create(0u, &parent_import_token, &parent_export_token);
ZX_CHECK(status == ZX_OK, status) << "zx_eventpair_create()";
parent_node_.BindAsRequest(&parent_export_token);
// Create a new node and add it as a child to the parent.
parent_node_id_ = scenic_session_.ImportResource(
fuchsia::ui::gfx::ImportSpec::NODE, std::move(parent_import_token));
node_id_ = scenic_session_.CreateEntityNode();
scenic_session_.AddNodeChild(parent_node_id_, node_id_);
// Setup entity node for the window.
parent_node_.AddChild(node_);
node_.AddChild(shape_node_);
shape_node_.SetMaterial(material_);
// Subscribe to metrics events from the parent node. These events are used to
// get the device pixel ratio for the screen.
scenic_session_.SetEventMask(parent_node_id_,
fuchsia::ui::gfx::kMetricsEventMask);
parent_node_.SetEventMask(fuchsia::ui::gfx::kMetricsEventMask);
// Create the view.
manager_->GetViewManager()->CreateView(
......@@ -74,31 +75,24 @@ ScenicWindow::ScenicWindow(
input_connection_.NewRequest().TakeChannel());
input_connection_->SetEventListener(input_listener_binding_.NewBinding());
// Add shape node for window.
shape_id_ = scenic_session_.CreateShapeNode();
scenic_session_.AddNodeChild(node_id_, shape_id_);
material_id_ = scenic_session_.CreateMaterial();
scenic_session_.SetNodeMaterial(shape_id_, material_id_);
// Call Present() to ensure that the scenic session commands are processed,
// which is necessary to receive metrics event from Scenic.
scenic_session_.Present();
scenic_session_.Present(
/*presentation_time=*/0, [](fuchsia::images::PresentationInfo info) {});
delegate_->OnAcceleratedWidgetAvailable(window_id_);
}
ScenicWindow::~ScenicWindow() {
scenic_session_.ReleaseResource(node_id_);
scenic_session_.ReleaseResource(parent_node_id_);
scenic_session_.ReleaseResource(shape_id_);
scenic_session_.ReleaseResource(material_id_);
manager_->RemoveWindow(window_id_, this);
view_.Unbind();
}
void ScenicWindow::SetTexture(ScenicSession::ResourceId texture) {
scenic_session_.SetMaterialTexture(material_id_, texture);
void ScenicWindow::SetTexture(const scenic::Image& image) {
material_.SetTexture(image);
}
void ScenicWindow::SetTexture(uint32_t image_id) {
material_.SetTexture(image_id);
}
gfx::Rect ScenicWindow::GetBounds() {
......@@ -199,18 +193,15 @@ void ScenicWindow::UpdateSize() {
if (screen)
screen->OnWindowBoundsChanged(window_id_, size_rect);
// Set node shape to rectangle that matches size of the view.
scenic::Rectangle rect(&scenic_session_, size_dips_.width(),
size_dips_.height());
shape_node_.SetShape(rect);
// Translate the node by half of the view dimensions to put it in the center
// of the view.
const float translation[] = {size_dips_.width() / 2.0,
size_dips_.height() / 2.0, 0.f};
// Set node shape to rectangle that matches size of the view.
ScenicSession::ResourceId rect_id =
scenic_session_.CreateRectangle(size_dips_.width(), size_dips_.height());
scenic_session_.SetNodeShape(shape_id_, rect_id);
scenic_session_.SetNodeTranslation(shape_id_, translation);
scenic_session_.ReleaseResource(rect_id);
scenic_session_.Present();
shape_node_.SetTranslation(size_dips_.width() / 2.0,
size_dips_.height() / 2.0, 0.f);
delegate_->OnBoundsChanged(size_rect);
}
......@@ -228,19 +219,19 @@ void ScenicWindow::OnPropertiesChanged(
callback();
}
void ScenicWindow::OnScenicError(const std::string& error) {
LOG(ERROR) << "ScenicSession failed: " << error;
void ScenicWindow::OnScenicError() {
LOG(ERROR) << "scenic::Session failed.";
delegate_->OnClosed();
}
void ScenicWindow::OnScenicEvents(
const std::vector<fuchsia::ui::scenic::Event>& events) {
for (const auto& event : events) {
fidl::VectorPtr<fuchsia::ui::scenic::Event> events) {
for (const auto& event : events.get()) {
if (!event.is_gfx() || !event.gfx().is_metrics())
continue;
auto& metrics = event.gfx().metrics();
if (metrics.node_id != parent_node_id_)
if (metrics.node_id != parent_node_.id())
continue;
device_pixel_ratio_ =
......
......@@ -7,6 +7,8 @@
#include <fuchsia/ui/input/cpp/fidl.h>
#include <fuchsia/ui/viewsv1/cpp/fidl.h>
#include <lib/ui/scenic/cpp/resources.h>
#include <lib/ui/scenic/cpp/session.h>
#include <string>
#include <vector>
......@@ -18,7 +20,6 @@
#include "ui/gfx/geometry/size_f.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/ozone/ozone_export.h"
#include "ui/ozone/platform/scenic/scenic_session.h"
#include "ui/platform_window/platform_window.h"
namespace ui {
......@@ -27,7 +28,6 @@ class ScenicWindowManager;
class PlatformWindowDelegate;
class OZONE_EXPORT ScenicWindow : public PlatformWindow,
public ScenicSessionListener,
public fuchsia::ui::viewsv1::ViewListener,
public fuchsia::ui::input::InputListener,
public InputEventDispatcherDelegate {
......@@ -42,11 +42,12 @@ class OZONE_EXPORT ScenicWindow : public PlatformWindow,
view_owner_request);
~ScenicWindow() override;
ScenicSession* scenic_session() { return &scenic_session_; }
ScenicSession::ResourceId node_id() const { return node_id_; }
scenic::Session* scenic_session() { return &scenic_session_; }
const scenic::Node& node() const { return node_; }
// Sets texture of the window to a scenic resource.
void SetTexture(ScenicSession::ResourceId texture);
// Sets texture of the window. |image| must be created in scenic_session().
void SetTexture(const scenic::Image& image);
void SetTexture(uint32_t image_id);
// PlatformWindow implementation.
gfx::Rect GetBounds() override;
......@@ -80,10 +81,9 @@ class OZONE_EXPORT ScenicWindow : public PlatformWindow,
void OnEvent(fuchsia::ui::input::InputEvent event,
OnEventCallback callback) override;
// ScenicSessionListener interface.
void OnScenicError(const std::string& error) override;
void OnScenicEvents(
const std::vector<fuchsia::ui::scenic::Event>& events) override;
// Callbacks for |scenic_session_|.
void OnScenicError();
void OnScenicEvents(fidl::VectorPtr<fuchsia::ui::scenic::Event> events);
// InputEventDispatcher::Delegate interface.
void DispatchEvent(ui::Event* event) override;
......@@ -106,19 +106,19 @@ class OZONE_EXPORT ScenicWindow : public PlatformWindow,
fidl::Binding<fuchsia::ui::viewsv1::ViewListener> view_listener_binding_;
// Scenic session used for all drawing operations in this View.
ScenicSession scenic_session_;
scenic::Session scenic_session_;
// Node ID in |scenic_session_| for the parent view.
ScenicSession::ResourceId parent_node_id_;
scenic::ImportNode parent_node_;
// Node ID in |scenic_session_| for the view.
ScenicSession::ResourceId node_id_;
scenic::EntityNode node_;
// Shape and material resource ids for the view in the context of the scenic
// session for the window. They are used to set shape and texture for the view
// Shape and material resources for the view in the context of
// |scenic_session_|. They are used to set shape and texture for the view
// node.
ScenicSession::ResourceId shape_id_;
ScenicSession::ResourceId material_id_;
scenic::ShapeNode shape_node_;
scenic::Material material_;
// The ratio used for translating device-independent coordinates to absolute
// pixel coordinates.
......
......@@ -20,32 +20,39 @@ ScenicWindowCanvas::Frame::Frame() = default;
ScenicWindowCanvas::Frame::~Frame() = default;
void ScenicWindowCanvas::Frame::Initialize(gfx::Size size,
ScenicSession* scenic) {
memory.Unmap();
scenic::Session* scenic) {
size_t bytes_per_row =
size.width() * SkColorTypeBytesPerPixel(kN32_SkColorType);
size_t buffer_size = bytes_per_row * size.height();
if (!memory.CreateAndMapAnonymous(buffer_size)) {
memory_region = base::UnsafeSharedMemoryRegion::Create(buffer_size);
memory_mapping = memory_region.Map();
if (!memory_region.IsValid()) {
LOG(WARNING) << "Failed to map memory for ScenicWindowCanvas.";
memory.Unmap();
memory_region = base::UnsafeSharedMemoryRegion();
memory_mapping = base::WritableSharedMemoryMapping();
surface.reset();
} else {
memory_id = scenic->CreateMemory(memory.GetReadOnlyHandle(),
fuchsia::images::MemoryType::HOST_MEMORY,
buffer_size);
surface = SkSurface::MakeRasterDirect(
SkImageInfo::MakeN32Premul(size.width(), size.height()),
memory.memory(), bytes_per_row);
dirty_region.setRect(gfx::RectToSkIRect(gfx::Rect(size)));
return;
}
scenic_memory = std::make_unique<scenic::Memory>(
scenic,
base::UnsafeSharedMemoryRegion::TakeHandleForSerialization(
memory_region.Duplicate())
.PassPlatformHandle(),
buffer_size, fuchsia::images::MemoryType::HOST_MEMORY);
surface = SkSurface::MakeRasterDirect(
SkImageInfo::MakeN32Premul(size.width(), size.height()),
memory_mapping.memory(), bytes_per_row);
dirty_region.setRect(gfx::RectToSkIRect(gfx::Rect(size)));
}
void ScenicWindowCanvas::Frame::CopyDirtyRegionFrom(const Frame& frame) {
int stride = surface->width() * SkColorTypeBytesPerPixel(kN32_SkColorType);
for (SkRegion::Iterator i(dirty_region); !i.done(); i.next()) {
uint8_t* dst_ptr =
static_cast<uint8_t*>(memory.memory()) +
static_cast<uint8_t*>(memory_mapping.memory()) +
i.rect().x() * SkColorTypeBytesPerPixel(kN32_SkColorType) +
i.rect().y() * stride;
frame.surface->readPixels(
......@@ -58,24 +65,16 @@ void ScenicWindowCanvas::Frame::CopyDirtyRegionFrom(const Frame& frame) {
ScenicWindowCanvas::ScenicWindowCanvas(ScenicWindow* window)
: window_(window) {}
ScenicWindowCanvas::~ScenicWindowCanvas() {
ScenicSession* scenic = window_->scenic_session();
for (int i = 0; i < kNumBuffers; ++i) {
if (!frames_[i].is_empty())
scenic->ReleaseResource(frames_[i].memory_id);
}
}
ScenicWindowCanvas::~ScenicWindowCanvas() = default;
void ScenicWindowCanvas::ResizeCanvas(const gfx::Size& viewport_size) {
viewport_size_ = viewport_size;
viewport_size_.SetToMax(gfx::Size(1, 1));
ScenicSession* scenic = window_->scenic_session();
scenic::Session* scenic = window_->scenic_session();
// Allocate new buffers with the new size.
for (int i = 0; i < kNumBuffers; ++i) {
if (!frames_[i].is_empty())
scenic->ReleaseResource(frames_[i].memory_id);
frames_[i].Initialize(viewport_size_, scenic);
}
}
......@@ -130,17 +129,14 @@ void ScenicWindowCanvas::PresentCanvas(const gfx::Rect& damage) {
}
// Create image that wraps the buffer and attach it as texture for the node.
ScenicSession* scenic = window_->scenic_session();
fuchsia::images::ImageInfo info;
info.width = viewport_size_.width();
info.height = viewport_size_.height();
info.stride =
viewport_size_.width() * SkColorTypeBytesPerPixel(kN32_SkColorType);
ScenicSession::ResourceId image_id = scenic->CreateImage(
frames_[current_frame_].memory_id, 0, std::move(info));
window_->SetTexture(image_id);
scenic->ReleaseResource(image_id);
scenic::Image image(*frames_[current_frame_].scenic_memory, 0,
std::move(info));
window_->SetTexture(image);
// Create release fence for the current buffer or reset it if it already
// exists.
......@@ -161,10 +157,10 @@ void ScenicWindowCanvas::PresentCanvas(const gfx::Rect& damage) {
auto status = frames_[current_frame_].release_fence.duplicate(
ZX_RIGHT_SAME_RIGHTS, &release_fence_dup);
ZX_CHECK(status == ZX_OK, status);
scenic->AddReleaseFence(std::move(release_fence_dup));
window_->scenic_session()->EnqueueReleaseFence(std::move(release_fence_dup));
// Present the frame.
scenic->Present();
window_->scenic_session()->Present(
/*presentation_time=*/0, [](fuchsia::images::PresentationInfo info) {});
// Move to the next buffer.
current_frame_ = (current_frame_ + 1) % kNumBuffers;
......
......@@ -5,14 +5,20 @@
#ifndef UI_OZONE_PLATFORM_SCENIC_SCENIC_WINDOW_CANVAS_H_
#define UI_OZONE_PLATFORM_SCENIC_SCENIC_WINDOW_CANVAS_H_
#include <lib/ui/scenic/cpp/resources.h>
#include "base/macros.h"
#include "base/memory/shared_memory.h"
#include "base/memory/shared_memory_mapping.h"
#include "base/memory/unsafe_shared_memory_region.h"
#include "third_party/skia/include/core/SkRegion.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "ui/gfx/geometry/size.h"
#include "ui/ozone/platform/scenic/scenic_session.h"
#include "ui/ozone/public/surface_ozone_canvas.h"
namespace scenic {
class Session;
} // namespace scenic
namespace ui {
class ScenicWindow;
......@@ -21,8 +27,8 @@ class ScenicWindow;
// ScenicWindow.
class ScenicWindowCanvas : public SurfaceOzoneCanvas {
public:
// |window| must outlive the surface. ScenicWindow owns the ScenicSession used
// in this class for all drawing operations.
// |window| must outlive the surface. ScenicWindow owns the scenic::Session
// used in this class for all drawing operations.
explicit ScenicWindowCanvas(ScenicWindow* window);
~ScenicWindowCanvas() override;
......@@ -43,23 +49,24 @@ class ScenicWindowCanvas : public SurfaceOzoneCanvas {
// Allocates and maps memory for a frame of |size| (in physical in pixels)
// and then registers it with |scenic|.
void Initialize(gfx::Size size, ScenicSession* scenic);
void Initialize(gfx::Size size, scenic::Session* scenic);
// Copies pixels covered by |dirty_region| from another |frame|.
void CopyDirtyRegionFrom(const Frame& frame);
bool is_empty() { return memory.mapped_size() == 0; }
bool is_empty() { return !surface; }
// Shared memory for the buffer.
base::SharedMemory memory;
base::UnsafeSharedMemoryRegion memory_region;
base::WritableSharedMemoryMapping memory_mapping;
// SkSurface that wraps |memory|.
// SkSurface that wraps |memory_mapping|.
sk_sp<SkSurface> surface;
// Valid only when |memory| is set.
ScenicSession::ResourceId memory_id;
// Scenic Memory resource for |memory_region|.
std::unique_ptr<scenic::Memory> scenic_memory;
// Fence that will be release by Scenic when it stops using this frame.
// Fence that will be released by Scenic when it stops using this frame.
zx::event release_fence;
// The region of the frame that's not up-to-date.
......
......@@ -4,6 +4,8 @@
#include "ui/ozone/platform/scenic/vulkan_implementation_scenic.h"
#include <lib/ui/scenic/cpp/commands.h>
#include <lib/ui/scenic/cpp/session.h>
#include <lib/zx/channel.h>
#include "base/files/file_path.h"
......@@ -75,13 +77,15 @@ VulkanImplementationScenic::CreateViewSurface(gfx::AcceleratedWidget window) {
ScenicWindow* scenic_window = scenic_window_manager_->GetWindow(window);
if (!scenic_window)
return nullptr;
ScenicSession* scenic_session = scenic_window->scenic_session();
scenic::Session* scenic_session = scenic_window->scenic_session();
fuchsia::images::ImagePipePtr image_pipe;
ScenicSession::ResourceId image_pipe_id =
scenic_session->CreateImagePipe(image_pipe.NewRequest());
uint32_t image_pipe_id = scenic_session->AllocResourceId();
scenic_session->Enqueue(
scenic::NewCreateImagePipeCmd(image_pipe_id, image_pipe.NewRequest()));
scenic_window->SetTexture(image_pipe_id);
scenic_session->ReleaseResource(image_pipe_id);
scenic_session->Present();
scenic_session->Present(/*presentation_time=*/0,
[](fuchsia::images::PresentationInfo info) {});
VkSurfaceKHR surface;
VkMagmaSurfaceCreateInfoKHR surface_create_info = {};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment