diff options
| author | Lizzy Fleckenstein <lizzy@vlhl.dev> | 2026-03-31 01:30:36 +0200 |
|---|---|---|
| committer | Lizzy Fleckenstein <lizzy@vlhl.dev> | 2026-03-31 01:30:36 +0200 |
| commit | 8e2ff15dbd3fe70fe2b52397b1eaba3fe2d7a5e8 (patch) | |
| tree | 925fa596210d1a1f01e00e0743a643f4552e7a7a /tools/Vulkan-Tools/cube/fuchsia | |
| parent | 1f17b4df127bd280e50d93a46ae93df704adc2b0 (diff) | |
| parent | 90bf5bc4fd8bea0d300f6564af256a51a34124b8 (diff) | |
| download | usermoji-8e2ff15dbd3fe70fe2b52397b1eaba3fe2d7a5e8.tar.xz | |
add tools/Vulkan-Tools
Diffstat (limited to 'tools/Vulkan-Tools/cube/fuchsia')
6 files changed, 446 insertions, 0 deletions
diff --git a/tools/Vulkan-Tools/cube/fuchsia/flatland_view.cpp b/tools/Vulkan-Tools/cube/fuchsia/flatland_view.cpp new file mode 100644 index 00000000..029c07d3 --- /dev/null +++ b/tools/Vulkan-Tools/cube/fuchsia/flatland_view.cpp @@ -0,0 +1,210 @@ +// Copyright (c) 2025 The Fuchsia Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "flatland_view.h" + +#include <fidl/fuchsia.ui.app/cpp/fidl.h> +#include <fidl/fuchsia.ui.composition/cpp/fidl.h> +#include <fidl/fuchsia.ui.views/cpp/fidl.h> +#include <lib/component/incoming/cpp/protocol.h> +#include <lib/component/outgoing/cpp/outgoing_directory.h> +#include <lib/syslog/cpp/macros.h> +#include <lib/syslog/global.h> +#include <lib/ui/scenic/cpp/view_creation_tokens.h> +#include <lib/ui/scenic/cpp/view_identity.h> + +#include <cinttypes> + +namespace { + +const char* const kTag = "FlatlandView"; + +const fuchsia_ui_composition::TransformId kRootTransform = {1}; +const fuchsia_ui_composition::ContentId kViewport = {1}; + +} // namespace + +// static +std::unique_ptr<FlatlandView> FlatlandView::Create(fidl::UnownedClientEnd<fuchsia_io::Directory> service_directory, + fuchsia_ui_views::ViewCreationToken view_creation_token, + ResizeCallback resize_callback, async_dispatcher_t* dispatcher) { + ZX_DEBUG_ASSERT(dispatcher != nullptr); + auto view = std::make_unique<FlatlandView>(std::move(resize_callback), dispatcher); + if (!view) return nullptr; + if (!view->Init(service_directory, std::move(view_creation_token))) return nullptr; + return view; +} + +FlatlandView::FlatlandView(ResizeCallback resize_callback, async_dispatcher_t* dispatcher) + : resize_callback_(std::move(resize_callback)), dispatcher_(dispatcher) { + ZX_DEBUG_ASSERT(dispatcher != nullptr); +} + +bool FlatlandView::Init(fidl::UnownedClientEnd<fuchsia_io::Directory> service_directory, + fuchsia_ui_views::ViewCreationToken view_creation_token) { + zx::result<fidl::ClientEnd<fuchsia_ui_composition::Flatland>> connect_result = + component::ConnectAt<fuchsia_ui_composition::Flatland>(service_directory); + if (connect_result.is_error()) { + FX_LOGS(ERROR) << "Failed to connect to Flatland: " << connect_result.status_string(); + return false; + } + fidl::ClientEnd<fuchsia_ui_composition::Flatland> flatland_client = std::move(connect_result).value(); + flatland_.Bind(std::move(flatland_client), dispatcher_, /*event_handler=*/this); + fit::result<fidl::OneWayError> set_debug_name_result = flatland_->SetDebugName({{.name = kTag}}); + if (set_debug_name_result.is_error()) { + FX_LOGS(ERROR) << "Failed to set debug name: " << set_debug_name_result.error_value().FormatDescription(); + } + + fit::result<fidl::OneWayError> create_transform_result = flatland_->CreateTransform(kRootTransform); + if (create_transform_result.is_error()) { + FX_LOGS(ERROR) << "Failed to call CreateTransform: " << create_transform_result.error_value().FormatDescription(); + return false; + } + + fit::result<fidl::OneWayError> set_root_transform_result = flatland_->SetRootTransform(kRootTransform); + if (set_root_transform_result.is_error()) { + FX_LOGS(ERROR) << "Failed to call SetRootTransform: " << set_root_transform_result.error_value().FormatDescription(); + return false; + } + + auto [parent_viewport_watcher_client, parent_viewport_watcher_server] = + fidl::Endpoints<fuchsia_ui_composition::ParentViewportWatcher>::Create(); + fit::result<fidl::OneWayError> create_view2_result = flatland_->CreateView2({{ + .token = std::move(view_creation_token), + .view_identity = scenic::cpp::NewViewIdentityOnCreation(), + .protocols = {}, + .parent_viewport_watcher = std::move(parent_viewport_watcher_server), + }}); + if (create_view2_result.is_error()) { + FX_LOGS(ERROR) << "Failed to call CreateView2: " << set_root_transform_result.error_value().FormatDescription(); + return false; + } + + parent_viewport_watcher_.Bind(std::move(parent_viewport_watcher_client), dispatcher_); + parent_viewport_watcher_->GetLayout().Then( + [this](fidl::Result<fuchsia_ui_composition::ParentViewportWatcher::GetLayout>& result) { + if (result.is_error()) { + FX_LOGS(ERROR) << "GetLayout() failed: " << result.error_value().FormatDescription(); + return; + } + OnGetLayout(std::move(result.value().info())); + }); + + zx::channel::create(0, &viewport_creation_token_.value(), &child_view_creation_token_.value()); + + return true; +} + +void FlatlandView::OnGetLayout(fuchsia_ui_composition::LayoutInfo info) { + ZX_DEBUG_ASSERT(info.logical_size().has_value()); + const fuchsia_math::SizeU& logical_size = info.logical_size().value(); + resize_callback_(logical_size.width(), logical_size.height()); + + fuchsia_ui_composition::ViewportProperties properties = {{.logical_size = logical_size}}; + if (viewport_creation_token_.value().is_valid()) { + // The first time that we receive layout information, create a viewport using the token that was stashed during Init(). + // External code will attach a view to this viewport via the token obtained from TakeChildViewCreationToken(). + auto [child_view_watcher_client, child_view_watcher_server] = + fidl::Endpoints<fuchsia_ui_composition::ChildViewWatcher>::Create(); + fit::result<fidl::OneWayError> create_viewport_result = flatland_->CreateViewport({{ + .viewport_id = kViewport, + .token = std::move(viewport_creation_token_), + .properties = std::move(properties), + .child_view_watcher = std::move(child_view_watcher_server), + }}); + if (create_viewport_result.is_error()) { + FX_LOGS(ERROR) << "Failed to call CreateViewport(): " << create_viewport_result.error_value().FormatDescription(); + return; + } + + fit::result<fidl::OneWayError> set_content_result = flatland_->SetContent({{ + .transform_id = kRootTransform, + .content_id = kViewport, + }}); + if (set_content_result.is_error()) { + FX_LOGS(ERROR) << "Failed to call SetContent(): " << set_content_result.error_value().FormatDescription(); + return; + } + } else { + auto set_viewport_properties_result = flatland_->SetViewportProperties({{ + .viewport_id = kViewport, + .properties = std::move(properties), + }}); + if (set_viewport_properties_result.is_error()) { + FX_LOGS(ERROR) << "Failed to call SetViewportProperties(): " + << set_viewport_properties_result.error_value().FormatDescription(); + return; + } + } + + Present(); + parent_viewport_watcher_->GetLayout().Then( + [this](fidl::Result<fuchsia_ui_composition::ParentViewportWatcher::GetLayout>& result) { + if (result.is_error()) { + FX_LOGS(ERROR) << "GetLayout() failed: " << result.error_value().FormatDescription(); + return; + } + OnGetLayout(std::move(result.value().info())); + }); +} + +void FlatlandView::OnError(fidl::Event<fuchsia_ui_composition::Flatland::OnError>& event) { + FX_LOGF(ERROR, kTag, "OnFlatlandError: %" PRIu32, static_cast<uint32_t>(event.error())); +} + +void FlatlandView::Present() { + if (present_credits_ == 0) { + pending_present_ = true; + return; + } + --present_credits_; + fuchsia_ui_composition::PresentArgs present_args = {{ + .requested_presentation_time = 0, + .acquire_fences = {}, + .release_fences = {}, + .unsquashable = false, + }}; + fit::result<fidl::OneWayError> present_result = flatland_->Present(std::move(present_args)); + if (present_result.is_error()) { + FX_LOGS(ERROR) << "Failed to call Present(): " << present_result.error_value().FormatDescription(); + } +} + +void FlatlandView::OnFramePresented(fidl::Event<fuchsia_ui_composition::Flatland::OnFramePresented>& event) {} + +void FlatlandView::OnNextFrameBegin(fidl::Event<fuchsia_ui_composition::Flatland::OnNextFrameBegin>& event) { + present_credits_ += event.values().additional_present_credits().value_or(0); + if (present_credits_ > 0 && pending_present_) { + Present(); + pending_present_ = false; + } +} + +FlatlandViewProviderService::FlatlandViewProviderService(CreateView2Callback create_view_callback, async_dispatcher_t* dispatcher) + : create_view_callback_(std::move(create_view_callback)), dispatcher_(dispatcher) { + ZX_DEBUG_ASSERT(dispatcher != nullptr); +} + +void FlatlandViewProviderService::CreateViewWithViewRef(CreateViewWithViewRefRequest& request, + CreateViewWithViewRefCompleter::Sync& completer) { + FX_NOTIMPLEMENTED() << "Only Flatland is supported. This is a Gfx ViewProvider method."; +} + +void FlatlandViewProviderService::CreateView2(CreateView2Request& request, CreateView2Completer::Sync& completer) { + create_view_callback_(std::move(request.args())); +} + +void FlatlandViewProviderService::HandleViewProviderRequest(fidl::ServerEnd<fuchsia_ui_app::ViewProvider> server_end) { + bindings_.AddBinding(dispatcher_, std::move(server_end), this, fidl::kIgnoreBindingClosure); +} diff --git a/tools/Vulkan-Tools/cube/fuchsia/flatland_view.h b/tools/Vulkan-Tools/cube/fuchsia/flatland_view.h new file mode 100644 index 00000000..01a8c6f9 --- /dev/null +++ b/tools/Vulkan-Tools/cube/fuchsia/flatland_view.h @@ -0,0 +1,102 @@ +// Copyright (c) 2025 The Fuchsia Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef FUCHSIA_FLATLAND_VIEW_H_ +#define FUCHSIA_FLATLAND_VIEW_H_ + +#include <fidl/fuchsia.io/cpp/fidl.h> +#include <fidl/fuchsia.ui.app/cpp/fidl.h> +#include <fidl/fuchsia.ui.composition/cpp/fidl.h> +#include <fidl/fuchsia.ui.views/cpp/fidl.h> +#include <lib/fit/function.h> +#include <lib/async/dispatcher.h> +#include <lib/syslog/cpp/macros.h> + +#include <cstdint> +#include <utility> + +#include <memory> + +// This class provides a convenient wrapper around the scenic fidl apis needed to get a Flatland +// View. Only SDK available constructs should be used so that this code may be leveraged by Vulkan +// applications built with the SDK. +class FlatlandView : public fidl::AsyncEventHandler<fuchsia_ui_composition::Flatland> { + public: + using ResizeCallback = fit::function<void(uint32_t width, uint32_t height)>; + + // Creates and initializes a `FlatlandView` instance. + // + // `dispatcher` must be non-null. + static std::unique_ptr<FlatlandView> Create(fidl::UnownedClientEnd<fuchsia_io::Directory> service_directory, + fuchsia_ui_views::ViewCreationToken view_creation_token, + ResizeCallback resize_callback, async_dispatcher_t* dispatcher); + + // Production code must use the `Create()` factory method. + // + // `dispatcher` must be non-null. + explicit FlatlandView(ResizeCallback resize_callback, async_dispatcher_t* dispatcher); + + fuchsia_ui_views::ViewCreationToken TakeChildViewCreationToken() { + FX_DCHECK(child_view_creation_token_.value().is_valid()); + return std::move(child_view_creation_token_); + } + + bool Init(fidl::UnownedClientEnd<fuchsia_io::Directory> service_directory, + fuchsia_ui_views::ViewCreationToken view_creation_token); + + private: + void OnNextFrameBegin(fidl::Event<fuchsia_ui_composition::Flatland::OnNextFrameBegin>& event) override; + void OnFramePresented(fidl::Event<fuchsia_ui_composition::Flatland::OnFramePresented>& event) override; + void OnError(fidl::Event<fuchsia_ui_composition::Flatland::OnError>& event) override; + + void OnGetLayout(fuchsia_ui_composition::LayoutInfo info); + void OnFlatlandError(fuchsia_ui_composition::FlatlandError error); + void Present(); + + fidl::SharedClient<fuchsia_ui_composition::Flatland> flatland_; + fidl::SharedClient<fuchsia_ui_composition::ParentViewportWatcher> parent_viewport_watcher_; + + fuchsia_ui_views::ViewportCreationToken viewport_creation_token_; + fuchsia_ui_views::ViewCreationToken child_view_creation_token_; + ResizeCallback resize_callback_; + + int64_t present_credits_ = 1; + bool pending_present_ = false; + + async_dispatcher_t* const dispatcher_; + + friend class FlatlandViewTest; +}; + +class FlatlandViewProviderService : public fidl::Server<fuchsia_ui_app::ViewProvider> { + public: + using CreateView2Callback = fit::function<void(fuchsia_ui_app::CreateView2Args args)>; + + // `dispatcher` must be non-null. + explicit FlatlandViewProviderService(CreateView2Callback create_view_callback, async_dispatcher_t* dispatcher); + + // fuchsia::ui::app::ViewProvider methods. + void CreateViewWithViewRef(CreateViewWithViewRefRequest& request, CreateViewWithViewRefCompleter::Sync& completer) override; + void CreateView2(CreateView2Request& request, CreateView2Completer::Sync& completer) override; + + void HandleViewProviderRequest(fidl::ServerEnd<fuchsia_ui_app::ViewProvider> server_end); + + private: + CreateView2Callback create_view_callback_; + fidl::ServerBindingGroup<fuchsia_ui_app::ViewProvider> bindings_; + + async_dispatcher_t* const dispatcher_; +}; + +#endif // FUCHSIA_FLATLAND_VIEW_H_ diff --git a/tools/Vulkan-Tools/cube/fuchsia/meta/vkcube-on-fb-protected.cml b/tools/Vulkan-Tools/cube/fuchsia/meta/vkcube-on-fb-protected.cml new file mode 100644 index 00000000..43d51a6e --- /dev/null +++ b/tools/Vulkan-Tools/cube/fuchsia/meta/vkcube-on-fb-protected.cml @@ -0,0 +1,27 @@ +// Copyright (c) 2025 The Fuchsia Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +{ + include: [ + "//src/lib/vulkan/swapchain/VkLayer_image_pipe_swapchain_fb.shard.cml", + "sys/testing/elf_test_runner.shard.cml", + ], + program: { + binary: "bin/vkcube", + args: [ + "--protected_output", + "--wsi", + "fuchsia_display", + ], + }, +} diff --git a/tools/Vulkan-Tools/cube/fuchsia/meta/vkcube-on-fb.cml b/tools/Vulkan-Tools/cube/fuchsia/meta/vkcube-on-fb.cml new file mode 100644 index 00000000..eaa78aae --- /dev/null +++ b/tools/Vulkan-Tools/cube/fuchsia/meta/vkcube-on-fb.cml @@ -0,0 +1,26 @@ +// Copyright (c) 2025 The Fuchsia Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +{ + include: [ + "//src/lib/vulkan/swapchain/VkLayer_image_pipe_swapchain_fb.shard.cml", + "sys/testing/elf_test_runner.shard.cml", + ], + program: { + binary: "bin/vkcube", + args: [ + "--wsi", + "fuchsia_display", + ], + }, +} diff --git a/tools/Vulkan-Tools/cube/fuchsia/meta/vkcube-on-scenic-protected.cml b/tools/Vulkan-Tools/cube/fuchsia/meta/vkcube-on-scenic-protected.cml new file mode 100644 index 00000000..3138b605 --- /dev/null +++ b/tools/Vulkan-Tools/cube/fuchsia/meta/vkcube-on-scenic-protected.cml @@ -0,0 +1,45 @@ +// Copyright (c) 2025 The Fuchsia Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +{ + include: [ "//src/lib/vulkan/swapchain/VkLayer_image_pipe_swapchain.shard.cml" ], + program: { + runner: "elf", + binary: "bin/vkcube", + args: [ + "--protected_output", + "--wsi", + "fuchsia_scenic", + ], + }, + capabilities: [ + { + protocol: [ "fuchsia.ui.app.ViewProvider" ], + }, + ], + use: [ + { + protocol: [ + "fuchsia.ui.composition.Allocator", + "fuchsia.ui.composition.Flatland", + ], + }, + ], + expose: [ + { + protocol: [ "fuchsia.ui.app.ViewProvider" ], + from: "self", + to: "parent", + }, + ], +} diff --git a/tools/Vulkan-Tools/cube/fuchsia/meta/vkcube-on-scenic.cml b/tools/Vulkan-Tools/cube/fuchsia/meta/vkcube-on-scenic.cml new file mode 100644 index 00000000..cf940b5b --- /dev/null +++ b/tools/Vulkan-Tools/cube/fuchsia/meta/vkcube-on-scenic.cml @@ -0,0 +1,36 @@ +// Copyright (c) 2025 The Fuchsia Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +{ + include: [ "//src/lib/vulkan/swapchain/VkLayer_image_pipe_swapchain.shard.cml" ], + program: { + runner: "elf", + binary: "bin/vkcube", + args: [ + "--wsi", + "fuchsia_scenic", + ], + }, + capabilities: [ + { + protocol: [ "fuchsia.ui.app.ViewProvider" ], + }, + ], + expose: [ + { + protocol: [ "fuchsia.ui.app.ViewProvider" ], + from: "self", + to: "parent", + }, + ], +} |
