[fuchsia][ozone] Remove "scenic" ozone platform
This change also: - removes dependency on lib/ui/scenic - moves //ui/ozone/platform/scenic/mojom to //ui/ozone/platform/flatland/mojom Fixed: 1424577 Change-Id: I03358d62019dfe70171ef16ec5d4f1ca31f65567 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4774544 Reviewed-by: Robert Sesek <rsesek@chromium.org> Reviewed-by: Nico Weber <thakis@chromium.org> Commit-Queue: Caroline Liu <carolineliu@google.com> Cr-Commit-Position: refs/heads/main@{#1189558}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
53dd4f8be5
commit
ca634cb03b
WATCHLISTS
build/config
docs
fuchsia_web/webengine
BUILD.gn
browser
media/fuchsia/video
ui
ozone
BUILD.gn
platform
flatland
BUILD.gnflatland_gpu_host.ccflatland_gpu_host.hflatland_gpu_service.hflatland_surface_factory.hflatland_window.hflatland_window_unittest.cc
mojom
ozone_platform_flatland.ccscenic
BUILD.gnDEPSDIR_METADATAOWNERSclient_native_pixmap_factory_scenic.ccclient_native_pixmap_factory_scenic.hoverlay_manager_scenic.ccoverlay_manager_scenic.hozone_platform_scenic.ccozone_platform_scenic.hsafe_presenter.ccsafe_presenter.hscenic_gpu_host.ccscenic_gpu_host.hscenic_gpu_service.ccscenic_gpu_service.hscenic_overlay_view.ccscenic_overlay_view.hscenic_screen.ccscenic_screen.hscenic_surface.ccscenic_surface.hscenic_surface_factory.ccscenic_surface_factory.hscenic_window.ccscenic_window.hscenic_window_canvas.ccscenic_window_canvas.hscenic_window_manager.ccscenic_window_manager.hsysmem_buffer_collection.ccsysmem_buffer_collection.hsysmem_buffer_manager.ccsysmem_buffer_manager.hsysmem_native_pixmap.ccsysmem_native_pixmap.hvulkan_implementation_scenic.ccvulkan_implementation_scenic.h
platform_window
@ -1617,8 +1617,7 @@
|
||||
'ui/gl/gl_.*ozone'
|
||||
},
|
||||
'ozone_fuchsia': {
|
||||
'filepath': 'ui/ozone/platform/flatland/|'\
|
||||
'ui/ozone/platform/scenic/'
|
||||
'filepath': 'ui/ozone/platform/flatland/',
|
||||
},
|
||||
'page_info' : {
|
||||
'filepath': 'chrome/browser/ui/page_info/'\
|
||||
|
@ -48,9 +48,6 @@ declare_args() {
|
||||
# Compile the 'headless' platform.
|
||||
ozone_platform_headless = false
|
||||
|
||||
# Compile the 'scenic' platform.
|
||||
ozone_platform_scenic = false
|
||||
|
||||
# Compile the 'flatland' platform.
|
||||
ozone_platform_flatland = false
|
||||
|
||||
@ -93,7 +90,6 @@ declare_args() {
|
||||
ozone_platform_x11 = true
|
||||
} else if (is_fuchsia) {
|
||||
ozone_platform = "flatland"
|
||||
ozone_platform_scenic = true
|
||||
ozone_platform_flatland = true
|
||||
}
|
||||
}
|
||||
@ -113,11 +109,11 @@ _ozone_extra_directory = get_path_info(ozone_extra_path, "dir")
|
||||
ozone_external_platform_visibility = [ "$_ozone_extra_directory/*" ]
|
||||
|
||||
if (is_a_target_toolchain) {
|
||||
assert(use_ozone || !(ozone_platform_cast || ozone_platform_drm ||
|
||||
ozone_platform_flatland ||
|
||||
ozone_platform_headless || ozone_platform_x11 ||
|
||||
ozone_platform_wayland || ozone_platform_scenic),
|
||||
"Must set use_ozone to select ozone platforms")
|
||||
assert(
|
||||
use_ozone || !(ozone_platform_cast || ozone_platform_drm ||
|
||||
ozone_platform_flatland || ozone_platform_headless ||
|
||||
ozone_platform_x11 || ozone_platform_wayland),
|
||||
"Must set use_ozone to select ozone platforms")
|
||||
}
|
||||
|
||||
# TODO(petermcneeley): Backwards compatiblity support for VM images.
|
||||
|
@ -357,7 +357,7 @@ ninja -C out/OzoneCaca content_shell
|
||||
### drm
|
||||
Ash-chrome client implementation.
|
||||
|
||||
### flatland / scenic
|
||||
### flatland
|
||||
For fuchsia.
|
||||
|
||||
## Communication
|
||||
|
@ -614,8 +614,6 @@ test("web_engine_browsertests") {
|
||||
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.mediacodec:fuchsia.mediacodec_hlcpp",
|
||||
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.mem:fuchsia.mem_hlcpp",
|
||||
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.input3:fuchsia.ui.input3_cpp",
|
||||
"//third_party/fuchsia-sdk/sdk/pkg/scenic_cpp",
|
||||
"//ui/gfx",
|
||||
"//ui/ozone",
|
||||
]
|
||||
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include <fuchsia/ui/gfx/cpp/fidl.h>
|
||||
#include <lib/fpromise/result.h>
|
||||
#include <lib/sys/cpp/component_context.h>
|
||||
#include <lib/ui/scenic/cpp/view_ref_pair.h>
|
||||
|
||||
#include <limits>
|
||||
|
||||
@ -79,6 +78,7 @@
|
||||
#include "ui/compositor/compositor.h"
|
||||
#include "ui/gfx/switches.h"
|
||||
#include "ui/ozone/public/ozone_switches.h"
|
||||
#include "ui/platform_window/fuchsia/view_ref_pair.h"
|
||||
#include "ui/wm/core/base_focus_rules.h"
|
||||
#include "url/gurl.h"
|
||||
#include "url/origin.h"
|
||||
@ -810,7 +810,7 @@ void FrameImpl::CreateView(fuchsia::ui::views::ViewToken view_token) {
|
||||
TRACE_EVENT(kWebEngineFidlCategory, "fuchsia.web/Frame.CreateView",
|
||||
perfetto::Flow::FromPointer(this));
|
||||
|
||||
auto view_ref_pair = scenic::ViewRefPair::New();
|
||||
auto view_ref_pair = ui::ViewRefPair::New();
|
||||
CreateViewImpl(std::move(view_token), std::move(view_ref_pair.control_ref),
|
||||
std::move(view_ref_pair.view_ref));
|
||||
}
|
||||
@ -844,7 +844,7 @@ void FrameImpl::CreateViewImpl(fuchsia::ui::views::ViewToken view_token,
|
||||
// If a View to this Frame is already active then disconnect it.
|
||||
DestroyWindowTreeHost();
|
||||
|
||||
scenic::ViewRefPair view_ref_pair;
|
||||
ui::ViewRefPair view_ref_pair;
|
||||
view_ref_pair.control_ref = std::move(control_ref);
|
||||
view_ref_pair.view_ref = std::move(view_ref);
|
||||
SetupWindowTreeHost(std::move(view_token), std::move(view_ref_pair));
|
||||
@ -872,7 +872,7 @@ void FrameImpl::CreateView2(fuchsia::web::CreateView2Args view_args) {
|
||||
// If a View to this Frame is already active then disconnect it.
|
||||
DestroyWindowTreeHost();
|
||||
|
||||
scenic::ViewRefPair view_ref_pair = scenic::ViewRefPair::New();
|
||||
auto view_ref_pair = ui::ViewRefPair::New();
|
||||
SetupWindowTreeHost(std::move(*view_args.mutable_view_creation_token()),
|
||||
std::move(view_ref_pair));
|
||||
|
||||
@ -1125,7 +1125,7 @@ void FrameImpl::EnableHeadlessRendering() {
|
||||
return;
|
||||
}
|
||||
|
||||
scenic::ViewRefPair view_ref_pair = scenic::ViewRefPair::New();
|
||||
auto view_ref_pair = ui::ViewRefPair::New();
|
||||
SetupWindowTreeHost(fuchsia::ui::views::ViewToken(),
|
||||
std::move(view_ref_pair));
|
||||
|
||||
@ -1159,7 +1159,7 @@ void FrameImpl::DisableHeadlessRendering() {
|
||||
}
|
||||
|
||||
void FrameImpl::SetupWindowTreeHost(fuchsia::ui::views::ViewToken view_token,
|
||||
scenic::ViewRefPair view_ref_pair) {
|
||||
ui::ViewRefPair view_ref_pair) {
|
||||
DCHECK(!window_tree_host_);
|
||||
|
||||
window_tree_host_ = std::make_unique<FrameWindowTreeHost>(
|
||||
@ -1172,7 +1172,7 @@ void FrameImpl::SetupWindowTreeHost(fuchsia::ui::views::ViewToken view_token,
|
||||
|
||||
void FrameImpl::SetupWindowTreeHost(
|
||||
fuchsia::ui::views::ViewCreationToken view_creation_token,
|
||||
scenic::ViewRefPair view_ref_pair) {
|
||||
ui::ViewRefPair view_ref_pair) {
|
||||
DCHECK(!window_tree_host_);
|
||||
|
||||
window_tree_host_ = std::make_unique<FrameWindowTreeHost>(
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include <fuchsia/web/cpp/fidl.h>
|
||||
#include <lib/fidl/cpp/binding_set.h>
|
||||
#include <lib/inspect/cpp/vmo/types.h>
|
||||
#include <lib/ui/scenic/cpp/view_ref_pair.h>
|
||||
#include <lib/zx/channel.h>
|
||||
|
||||
#include <list>
|
||||
@ -40,6 +39,7 @@
|
||||
#include "third_party/blink/public/common/web_preferences/web_preferences.h"
|
||||
#include "ui/accessibility/platform/fuchsia/accessibility_bridge_fuchsia_impl.h"
|
||||
#include "ui/aura/window_tree_host.h"
|
||||
#include "ui/platform_window/fuchsia/view_ref_pair.h"
|
||||
#include "ui/wm/core/focus_controller.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
@ -187,14 +187,14 @@ class WEB_ENGINE_EXPORT FrameImpl : public fuchsia::web::Frame,
|
||||
// Creates and initializes WindowTreeHost for the view with the specified
|
||||
// |view_token|. |view_token| may be uninitialized in headless mode.
|
||||
void SetupWindowTreeHost(fuchsia::ui::views::ViewToken view_token,
|
||||
scenic::ViewRefPair view_ref_pair);
|
||||
ui::ViewRefPair view_ref_pair);
|
||||
|
||||
// Creates and initializes WindowTreeHost for the view with the specified
|
||||
// |view_creation_token|. |view_creation_token| may be uninitialized in
|
||||
// headless mode.
|
||||
void SetupWindowTreeHost(
|
||||
fuchsia::ui::views::ViewCreationToken view_creation_token,
|
||||
scenic::ViewRefPair view_ref_pair);
|
||||
ui::ViewRefPair view_ref_pair);
|
||||
|
||||
// Initializes WindowTreeHost.
|
||||
void InitWindowTreeHost();
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
#include <fuchsia/element/cpp/fidl.h>
|
||||
#include <lib/ui/scenic/cpp/view_creation_tokens.h>
|
||||
#include <lib/ui/scenic/cpp/view_token_pair.h>
|
||||
#include <lib/zx/time.h>
|
||||
|
||||
#include "base/fuchsia/fuchsia_logging.h"
|
||||
@ -96,15 +95,6 @@ std::string GetDocumentVisibilityState(fuchsia::web::Frame* frame) {
|
||||
return visibility->data;
|
||||
}
|
||||
|
||||
::fuchsia::ui::views::ViewRef CloneViewRef(
|
||||
const ::fuchsia::ui::views::ViewRef& view_ref) {
|
||||
::fuchsia::ui::views::ViewRef dup;
|
||||
zx_status_t status =
|
||||
view_ref.reference.duplicate(ZX_RIGHT_SAME_RIGHTS, &dup.reference);
|
||||
ZX_CHECK(status == ZX_OK, status) << "zx_object_duplicate";
|
||||
return dup;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// Defines a suite of tests that exercise Frame-level functionality, such as
|
||||
@ -330,8 +320,11 @@ IN_PROC_BROWSER_TEST_F(FrameImplTest, ContextDeletedBeforeFrameWithView) {
|
||||
base::RunLoop().RunUntilIdle();
|
||||
FrameImpl* frame_impl = context_impl()->GetFrameImplForTest(&frame.ptr());
|
||||
|
||||
auto view_tokens = scenic::ViewTokenPair::New();
|
||||
frame->CreateView(std::move(view_tokens.view_token));
|
||||
scenic::ViewCreationTokenPair token_pair =
|
||||
scenic::ViewCreationTokenPair::New();
|
||||
fuchsia::web::CreateView2Args create_view_args;
|
||||
create_view_args.set_view_creation_token(std::move(token_pair.view_token));
|
||||
frame->CreateView2(std::move(create_view_args));
|
||||
base::RunLoop().RunUntilIdle();
|
||||
EXPECT_TRUE(frame_impl->has_view_for_test());
|
||||
|
||||
@ -878,17 +871,16 @@ IN_PROC_BROWSER_TEST_F(FrameImplTest, Stop) {
|
||||
#define MAYBE_SetPageScale DISABLED_SetPageScale
|
||||
#endif
|
||||
IN_PROC_BROWSER_TEST_F(FrameImplTest, MAYBE_SetPageScale) {
|
||||
// This test uses the `fuchsia.ui.gfx` variant of `Frame.CreateView*()`.
|
||||
ASSERT_EQ(ui::OzonePlatform::GetInstance()->GetPlatformNameForTest(),
|
||||
"scenic");
|
||||
"flatland");
|
||||
|
||||
auto frame = FrameForTest::Create(context(), {});
|
||||
|
||||
auto view_tokens = scenic::ViewTokenPair::New();
|
||||
auto view_ref_pair = scenic::ViewRefPair::New();
|
||||
frame->CreateViewWithViewRef(std::move(view_tokens.view_token),
|
||||
std::move(view_ref_pair.control_ref),
|
||||
CloneViewRef(view_ref_pair.view_ref));
|
||||
scenic::ViewCreationTokenPair token_pair =
|
||||
scenic::ViewCreationTokenPair::New();
|
||||
fuchsia::web::CreateView2Args create_view_args;
|
||||
create_view_args.set_view_creation_token(std::move(token_pair.view_token));
|
||||
frame->CreateView2(std::move(create_view_args));
|
||||
|
||||
// Attach the View to a Presenter, the page should be visible.
|
||||
auto presenter = base::ComponentContextForProcess()
|
||||
@ -900,8 +892,8 @@ IN_PROC_BROWSER_TEST_F(FrameImplTest, MAYBE_SetPageScale) {
|
||||
});
|
||||
|
||||
::fuchsia::element::ViewSpec view_spec;
|
||||
view_spec.set_view_holder_token(std::move(view_tokens.view_holder_token));
|
||||
view_spec.set_view_ref(std::move(view_ref_pair.view_ref));
|
||||
view_spec.set_viewport_creation_token(std::move(token_pair.viewport_token));
|
||||
view_spec.set_annotations({});
|
||||
::fuchsia::element::ViewControllerPtr view_controller;
|
||||
presenter->PresentView(std::move(view_spec), nullptr,
|
||||
view_controller.NewRequest(),
|
||||
@ -979,15 +971,12 @@ IN_PROC_BROWSER_TEST_F(FrameImplTest, MAYBE_SetPageScale) {
|
||||
// Create another frame. Verify that the scale factor is not applied to the
|
||||
// new frame.
|
||||
auto frame2 = FrameForTest::Create(context(), {});
|
||||
token_pair = scenic::ViewCreationTokenPair::New();
|
||||
create_view_args.set_view_creation_token(std::move(token_pair.view_token));
|
||||
frame2->CreateView2(std::move(create_view_args));
|
||||
|
||||
view_tokens = scenic::ViewTokenPair::New();
|
||||
view_ref_pair = scenic::ViewRefPair::New();
|
||||
frame2->CreateViewWithViewRef(std::move(view_tokens.view_token),
|
||||
std::move(view_ref_pair.control_ref),
|
||||
CloneViewRef(view_ref_pair.view_ref));
|
||||
|
||||
view_spec.set_view_holder_token(std::move(view_tokens.view_holder_token));
|
||||
view_spec.set_view_ref(std::move(view_ref_pair.view_ref));
|
||||
view_spec.set_viewport_creation_token(std::move(token_pair.viewport_token));
|
||||
view_spec.set_annotations({});
|
||||
presenter->PresentView(std::move(view_spec), nullptr,
|
||||
view_controller.NewRequest(), [](auto) {});
|
||||
|
||||
@ -1024,8 +1013,11 @@ IN_PROC_BROWSER_TEST_F(FrameImplTest, RecreateView) {
|
||||
frame.navigation_listener().RunUntilUrlAndTitleEquals(page1_url, kPage1Title);
|
||||
|
||||
// Request a View from the Frame, and pump the loop to process the request.
|
||||
auto view_tokens = scenic::ViewTokenPair::New();
|
||||
frame->CreateView(std::move(view_tokens.view_token));
|
||||
scenic::ViewCreationTokenPair token_pair =
|
||||
scenic::ViewCreationTokenPair::New();
|
||||
fuchsia::web::CreateView2Args create_view_args;
|
||||
create_view_args.set_view_creation_token(std::move(token_pair.view_token));
|
||||
frame->CreateView2(std::move(create_view_args));
|
||||
base::RunLoop().RunUntilIdle();
|
||||
EXPECT_TRUE(frame_impl->has_view_for_test());
|
||||
|
||||
@ -1037,8 +1029,9 @@ IN_PROC_BROWSER_TEST_F(FrameImplTest, RecreateView) {
|
||||
frame.navigation_listener().RunUntilUrlAndTitleEquals(page2_url, kPage2Title);
|
||||
|
||||
// Create new View tokens and request a new view.
|
||||
auto view_tokens2 = scenic::ViewTokenPair::New();
|
||||
frame->CreateView(std::move(view_tokens2.view_token));
|
||||
token_pair = scenic::ViewCreationTokenPair::New();
|
||||
create_view_args.set_view_creation_token(std::move(token_pair.view_token));
|
||||
frame->CreateView2(std::move(create_view_args));
|
||||
base::RunLoop().RunUntilIdle();
|
||||
EXPECT_TRUE(frame_impl->has_view_for_test());
|
||||
|
||||
|
@ -25,7 +25,7 @@ fuchsia::ui::views::ViewRef DupViewRef(
|
||||
}
|
||||
|
||||
ui::PlatformWindowInitProperties CreatePlatformWindowInitProperties(
|
||||
scenic::ViewRefPair view_ref_pair,
|
||||
ui::ViewRefPair view_ref_pair,
|
||||
ui::ScenicWindowDelegate* scenic_window_delegate) {
|
||||
ui::PlatformWindowInitProperties properties;
|
||||
properties.view_ref_pair = std::move(view_ref_pair);
|
||||
@ -66,7 +66,7 @@ class FrameWindowTreeHost::WindowParentingClientImpl
|
||||
|
||||
FrameWindowTreeHost::FrameWindowTreeHost(
|
||||
fuchsia::ui::views::ViewToken view_token,
|
||||
scenic::ViewRefPair view_ref_pair,
|
||||
ui::ViewRefPair view_ref_pair,
|
||||
content::WebContents* web_contents,
|
||||
OnPixelScaleUpdateCallback on_pixel_scale_update)
|
||||
: view_ref_(DupViewRef(view_ref_pair.view_ref)),
|
||||
@ -85,7 +85,7 @@ FrameWindowTreeHost::FrameWindowTreeHost(
|
||||
|
||||
FrameWindowTreeHost::FrameWindowTreeHost(
|
||||
fuchsia::ui::views::ViewCreationToken view_creation_token,
|
||||
scenic::ViewRefPair view_ref_pair,
|
||||
ui::ViewRefPair view_ref_pair,
|
||||
content::WebContents* web_contents,
|
||||
OnPixelScaleUpdateCallback on_pixel_scale_update)
|
||||
: view_ref_(DupViewRef(view_ref_pair.view_ref)),
|
||||
|
@ -5,11 +5,12 @@
|
||||
#ifndef FUCHSIA_WEB_WEBENGINE_BROWSER_FRAME_WINDOW_TREE_HOST_H_
|
||||
#define FUCHSIA_WEB_WEBENGINE_BROWSER_FRAME_WINDOW_TREE_HOST_H_
|
||||
|
||||
#include <lib/ui/scenic/cpp/view_ref_pair.h>
|
||||
#include <fuchsia/ui/views/cpp/fidl.h>
|
||||
|
||||
#include "fuchsia_web/webengine/web_engine_export.h"
|
||||
#include "ui/aura/window_tree_host_platform.h"
|
||||
#include "ui/platform_window/fuchsia/scenic_window_delegate.h"
|
||||
#include "ui/platform_window/fuchsia/view_ref_pair.h"
|
||||
|
||||
namespace content {
|
||||
class WebContents;
|
||||
@ -24,11 +25,11 @@ class WEB_ENGINE_EXPORT FrameWindowTreeHost final
|
||||
using OnPixelScaleUpdateCallback = base::RepeatingCallback<void(float)>;
|
||||
|
||||
FrameWindowTreeHost(fuchsia::ui::views::ViewToken view_token,
|
||||
scenic::ViewRefPair view_ref_pair,
|
||||
ui::ViewRefPair view_ref_pair,
|
||||
content::WebContents* web_contents,
|
||||
OnPixelScaleUpdateCallback on_pixel_scale_update);
|
||||
FrameWindowTreeHost(fuchsia::ui::views::ViewCreationToken view_creation_token,
|
||||
scenic::ViewRefPair view_ref_pair,
|
||||
ui::ViewRefPair view_ref_pair,
|
||||
content::WebContents* web_contents,
|
||||
OnPixelScaleUpdateCallback on_pixel_scale_update);
|
||||
~FrameWindowTreeHost() override;
|
||||
|
@ -653,8 +653,9 @@ void FuchsiaVideoDecoder::OnStreamProcessorOutputPacket(
|
||||
// luma (see fxbug.dev/13677). Assume they are cosited with luma. YCbCr info
|
||||
// here must match the values passed for the same buffer in
|
||||
// ui::SysmemBufferCollection::CreateVkImage() (see
|
||||
// ui/ozone/platform/scenic/sysmem_buffer_collection.cc). |format_features|
|
||||
// are resolved later in the GPU process before this info is passed to Skia.
|
||||
// ui/ozone/platform/flatland/flatland_sysmem_buffer_collection.cc).
|
||||
// |format_features| are resolved later in the GPU process before this info is
|
||||
// passed to Skia.
|
||||
frame->set_ycbcr_info(gpu::VulkanYCbCrInfo(
|
||||
vk_format, /*external_format=*/0, ycbcr_conversion,
|
||||
VK_SAMPLER_YCBCR_RANGE_ITU_NARROW, VK_CHROMA_LOCATION_COSITED_EVEN,
|
||||
|
@ -65,11 +65,6 @@ if (ozone_platform_x11) {
|
||||
ozone_platform_ui_test_support_deps += [ "platform/x11:test_support" ]
|
||||
}
|
||||
|
||||
if (ozone_platform_scenic) {
|
||||
ozone_platforms += [ "scenic" ]
|
||||
ozone_platform_deps += [ "platform/scenic" ]
|
||||
}
|
||||
|
||||
if (ozone_platform_flatland) {
|
||||
ozone_platforms += [ "flatland" ]
|
||||
ozone_platform_deps += [ "platform/flatland" ]
|
||||
|
@ -70,12 +70,12 @@ source_set("flatland") {
|
||||
"//ui/events/ozone/layout",
|
||||
"//ui/ozone:ozone_base",
|
||||
"//ui/ozone/common",
|
||||
"//ui/ozone/platform/scenic/mojom",
|
||||
"//ui/ozone/platform/flatland/mojom",
|
||||
]
|
||||
|
||||
public_deps = [
|
||||
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.element:fuchsia.element_hlcpp",
|
||||
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.composition:fuchsia.ui.composition_hlcpp",
|
||||
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.gfx:fuchsia.ui.gfx_hlcpp",
|
||||
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.input3:fuchsia.ui.input3_cpp",
|
||||
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.pointer:fuchsia.ui.pointer_cpp",
|
||||
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.pointer:fuchsia.ui.pointer_cpp_hlcpp_conversion",
|
||||
|
@ -13,8 +13,8 @@
|
||||
#include "mojo/public/cpp/system/message_pipe.h"
|
||||
#include "ui/ozone/platform/flatland/flatland_window.h"
|
||||
#include "ui/ozone/platform/flatland/flatland_window_manager.h"
|
||||
#include "ui/ozone/platform/scenic/mojom/scenic_gpu_host.mojom.h"
|
||||
#include "ui/ozone/platform/scenic/mojom/scenic_gpu_service.mojom.h"
|
||||
#include "ui/ozone/platform/flatland/mojom/scenic_gpu_host.mojom.h"
|
||||
#include "ui/ozone/platform/flatland/mojom/scenic_gpu_service.mojom.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -14,8 +14,8 @@
|
||||
#include "mojo/public/cpp/bindings/pending_remote.h"
|
||||
#include "mojo/public/cpp/bindings/receiver.h"
|
||||
#include "mojo/public/cpp/bindings/remote.h"
|
||||
#include "ui/ozone/platform/scenic/mojom/scenic_gpu_host.mojom.h"
|
||||
#include "ui/ozone/platform/scenic/mojom/scenic_gpu_service.mojom.h"
|
||||
#include "ui/ozone/platform/flatland/mojom/scenic_gpu_host.mojom.h"
|
||||
#include "ui/ozone/platform/flatland/mojom/scenic_gpu_service.mojom.h"
|
||||
#include "ui/ozone/public/gpu_platform_support_host.h"
|
||||
|
||||
namespace ui {
|
||||
|
@ -10,8 +10,8 @@
|
||||
#include "mojo/public/cpp/bindings/pending_receiver.h"
|
||||
#include "mojo/public/cpp/bindings/pending_remote.h"
|
||||
#include "mojo/public/cpp/bindings/receiver_set.h"
|
||||
#include "ui/ozone/platform/scenic/mojom/scenic_gpu_host.mojom.h"
|
||||
#include "ui/ozone/platform/scenic/mojom/scenic_gpu_service.mojom.h"
|
||||
#include "ui/ozone/platform/flatland/mojom/scenic_gpu_host.mojom.h"
|
||||
#include "ui/ozone/platform/flatland/mojom/scenic_gpu_service.mojom.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include "mojo/public/cpp/bindings/remote.h"
|
||||
#include "mojo/public/cpp/system/handle.h"
|
||||
#include "ui/ozone/platform/flatland/flatland_sysmem_buffer_manager.h"
|
||||
#include "ui/ozone/platform/scenic/mojom/scenic_gpu_host.mojom.h"
|
||||
#include "ui/ozone/platform/flatland/mojom/scenic_gpu_host.mojom.h"
|
||||
#include "ui/ozone/public/gl_ozone.h"
|
||||
#include "ui/ozone/public/surface_factory_ozone.h"
|
||||
|
||||
|
@ -6,9 +6,9 @@
|
||||
#define UI_OZONE_PLATFORM_FLATLAND_FLATLAND_WINDOW_H_
|
||||
|
||||
#include <fidl/fuchsia.ui.input3/cpp/fidl.h>
|
||||
#include <fuchsia/element/cpp/fidl.h>
|
||||
#include <fuchsia/ui/composition/cpp/fidl.h>
|
||||
#include <fuchsia/ui/views/cpp/fidl.h>
|
||||
#include <lib/ui/scenic/cpp/view_ref_pair.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include <lib/ui/scenic/cpp/testing/fake_flatland.h>
|
||||
#include <lib/ui/scenic/cpp/testing/fake_touch_source.h>
|
||||
#include <lib/ui/scenic/cpp/testing/fake_view_ref_focused.h>
|
||||
#include <lib/ui/scenic/cpp/view_creation_tokens.h>
|
||||
#include <lib/zx/channel.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@ -25,6 +25,7 @@
|
||||
#include "ui/events/fuchsia/util/pointer_event_utility.h"
|
||||
#include "ui/ozone/platform/flatland/flatland_window_manager.h"
|
||||
#include "ui/ozone/test/mock_platform_window_delegate.h"
|
||||
#include "ui/platform_window/fuchsia/view_ref_pair.h"
|
||||
|
||||
using ::scenic::FakeGraph;
|
||||
using ::scenic::FakeTransform;
|
||||
@ -126,15 +127,19 @@ class FlatlandWindowTest : public ::testing::Test {
|
||||
void CreateWindow() {
|
||||
EXPECT_FALSE(flatland_window_);
|
||||
|
||||
auto token_pair = scenic::ViewCreationTokenPair::New();
|
||||
viewport_token_ = std::move(token_pair.viewport_token);
|
||||
fuchsia::ui::views::ViewCreationToken view_token;
|
||||
fuchsia::ui::views::ViewportCreationToken viewport_token;
|
||||
auto status =
|
||||
zx::channel::create(0, &viewport_token.value, &view_token.value);
|
||||
CHECK_EQ(ZX_OK, status);
|
||||
viewport_token_ = std::move(viewport_token);
|
||||
|
||||
EXPECT_CALL(window_delegate_, OnAcceleratedWidgetAvailable(_))
|
||||
.WillOnce(SaveArg<0>(&window_widget_));
|
||||
|
||||
PlatformWindowInitProperties properties;
|
||||
properties.view_ref_pair = scenic::ViewRefPair::New();
|
||||
properties.view_creation_token = std::move(token_pair.view_token);
|
||||
properties.view_ref_pair = ViewRefPair::New();
|
||||
properties.view_creation_token = std::move(view_token);
|
||||
flatland_window_ = std::make_unique<FlatlandWindow>(
|
||||
&window_manager_, &window_delegate_, std::move(properties));
|
||||
}
|
||||
@ -330,8 +335,12 @@ TEST_F(FlatlandWindowTest, WaitsForNonZeroSizeToAttachSurfaceContent) {
|
||||
task_environment_.RunUntilIdle();
|
||||
|
||||
// Try attaching the content. It should only be a closure.
|
||||
auto token_pair = scenic::ViewCreationTokenPair::New();
|
||||
flatland_window_->AttachSurfaceContent(std::move(token_pair.viewport_token));
|
||||
fuchsia::ui::views::ViewCreationToken view_token;
|
||||
fuchsia::ui::views::ViewportCreationToken viewport_token;
|
||||
auto status =
|
||||
zx::channel::create(0, &viewport_token.value, &view_token.value);
|
||||
CHECK_EQ(ZX_OK, status);
|
||||
flatland_window_->AttachSurfaceContent(std::move(viewport_token));
|
||||
EXPECT_TRUE(HasPendingAttachSurfaceContentClosure());
|
||||
|
||||
// Setting layout info should trigger the closure and delegate calls.
|
||||
@ -363,9 +372,8 @@ TEST_F(FlatlandWindowTest, WaitsForNonZeroSizeToAttachSurfaceContent) {
|
||||
task_environment_.RunUntilIdle();
|
||||
EXPECT_EQ(2u, presents_called);
|
||||
EXPECT_THAT(fake_flatland_.graph(),
|
||||
IsWindowGraph(
|
||||
parent_viewport_watcher(), viewport_token_,
|
||||
Contains(IsViewport(token_pair.view_token, expected_size))));
|
||||
IsWindowGraph(parent_viewport_watcher(), viewport_token_,
|
||||
Contains(IsViewport(view_token, expected_size))));
|
||||
}
|
||||
|
||||
// Verify that surface is cleared when the window is disconnected from the
|
||||
@ -378,8 +386,12 @@ TEST_F(FlatlandWindowTest, ResetSurfaceOnDisconnect) {
|
||||
task_environment_.RunUntilIdle();
|
||||
|
||||
// Try attaching the content. It should only be a closure.
|
||||
auto token_pair = scenic::ViewCreationTokenPair::New();
|
||||
flatland_window_->AttachSurfaceContent(std::move(token_pair.viewport_token));
|
||||
fuchsia::ui::views::ViewCreationToken view_token;
|
||||
fuchsia::ui::views::ViewportCreationToken viewport_token;
|
||||
auto status =
|
||||
zx::channel::create(0, &viewport_token.value, &view_token.value);
|
||||
CHECK_EQ(ZX_OK, status);
|
||||
flatland_window_->AttachSurfaceContent(std::move(viewport_token));
|
||||
|
||||
SetWindowStatus(
|
||||
fuchsia::ui::composition::ParentViewportStatus::CONNECTED_TO_DISPLAY);
|
||||
@ -434,8 +446,12 @@ TEST_F(FlatlandWindowTest, SurfaceHasHitTestHitShield) {
|
||||
// Spin the loop to propagate layout.
|
||||
task_environment_.RunUntilIdle();
|
||||
|
||||
auto token_pair = scenic::ViewCreationTokenPair::New();
|
||||
flatland_window_->AttachSurfaceContent(std::move(token_pair.viewport_token));
|
||||
fuchsia::ui::views::ViewCreationToken view_token;
|
||||
fuchsia::ui::views::ViewportCreationToken viewport_token;
|
||||
auto status =
|
||||
zx::channel::create(0, &viewport_token.value, &view_token.value);
|
||||
CHECK_EQ(ZX_OK, status);
|
||||
flatland_window_->AttachSurfaceContent(std::move(viewport_token));
|
||||
|
||||
// Show() the window, to trigger creation of the scene graph, including
|
||||
// surface and hit shield.
|
||||
@ -449,12 +465,12 @@ TEST_F(FlatlandWindowTest, SurfaceHasHitTestHitShield) {
|
||||
task_environment_.RunUntilIdle();
|
||||
|
||||
// Surface should be accompanied by input shield, in that order.
|
||||
EXPECT_THAT(fake_flatland_.graph(),
|
||||
Field("root_transform", &FakeGraph::root_transform,
|
||||
Pointee(Field("children", &FakeTransform::children,
|
||||
ElementsAre(IsViewport(token_pair.view_token,
|
||||
expected_size),
|
||||
IsHitShield())))));
|
||||
EXPECT_THAT(
|
||||
fake_flatland_.graph(),
|
||||
Field("root_transform", &FakeGraph::root_transform,
|
||||
Pointee(Field("children", &FakeTransform::children,
|
||||
ElementsAre(IsViewport(view_token, expected_size),
|
||||
IsHitShield())))));
|
||||
}
|
||||
|
||||
class ParameterizedViewInsetTest : public FlatlandWindowTest,
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
module ui.mojom;
|
||||
|
||||
import "ui/ozone/platform/scenic/mojom/scenic_gpu_host.mojom";
|
||||
import "ui/ozone/platform/flatland/mojom/scenic_gpu_host.mojom";
|
||||
|
||||
// GPU process service that enables presentation to Scenic.
|
||||
interface ScenicGpuService {
|
@ -33,14 +33,15 @@
|
||||
#include "ui/ozone/platform/flatland/flatland_sysmem_buffer_collection.h"
|
||||
#include "ui/ozone/platform/flatland/flatland_window.h"
|
||||
#include "ui/ozone/platform/flatland/flatland_window_manager.h"
|
||||
#include "ui/ozone/platform/flatland/mojom/scenic_gpu_service.mojom.h"
|
||||
#include "ui/ozone/platform/flatland/overlay_manager_flatland.h"
|
||||
#include "ui/ozone/platform/scenic/mojom/scenic_gpu_service.mojom.h"
|
||||
#include "ui/ozone/platform_selection.h"
|
||||
#include "ui/ozone/public/gpu_platform_support_host.h"
|
||||
#include "ui/ozone/public/input_controller.h"
|
||||
#include "ui/ozone/public/ozone_platform.h"
|
||||
#include "ui/ozone/public/ozone_switches.h"
|
||||
#include "ui/ozone/public/system_input_injector.h"
|
||||
#include "ui/platform_window/fuchsia/view_ref_pair.h"
|
||||
#include "ui/platform_window/platform_window_init_properties.h"
|
||||
|
||||
#if BUILDFLAG(IS_FUCHSIA)
|
||||
@ -105,7 +106,7 @@ class OzonePlatformFlatland : public OzonePlatform,
|
||||
zx::channel::create(0, &parent_token.value, &child_token.value);
|
||||
CHECK_EQ(ZX_OK, status) << "zx_channel_create";
|
||||
properties.view_creation_token = std::move(child_token);
|
||||
properties.view_ref_pair = scenic::ViewRefPair::New();
|
||||
properties.view_ref_pair = ::ui::ViewRefPair::New();
|
||||
properties.view_controller =
|
||||
::ui::fuchsia::GetFlatlandViewPresenter().Run(
|
||||
std::move(parent_token));
|
||||
|
@ -1,100 +0,0 @@
|
||||
# Copyright 2018 The Chromium Authors
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
assert(is_fuchsia)
|
||||
|
||||
import("//build/config/dcheck_always_on.gni")
|
||||
import("//gpu/vulkan/features.gni")
|
||||
|
||||
assert(enable_vulkan)
|
||||
|
||||
visibility = [ "//ui/ozone/*" ]
|
||||
|
||||
source_set("scenic") {
|
||||
sources = [
|
||||
"client_native_pixmap_factory_scenic.cc",
|
||||
"client_native_pixmap_factory_scenic.h",
|
||||
"overlay_manager_scenic.cc",
|
||||
"overlay_manager_scenic.h",
|
||||
"ozone_platform_scenic.cc",
|
||||
"ozone_platform_scenic.h",
|
||||
"safe_presenter.cc",
|
||||
"safe_presenter.h",
|
||||
"scenic_gpu_host.cc",
|
||||
"scenic_gpu_host.h",
|
||||
"scenic_gpu_service.cc",
|
||||
"scenic_gpu_service.h",
|
||||
"scenic_overlay_view.cc",
|
||||
"scenic_overlay_view.h",
|
||||
"scenic_screen.cc",
|
||||
"scenic_screen.h",
|
||||
"scenic_surface.cc",
|
||||
"scenic_surface.h",
|
||||
"scenic_surface_factory.cc",
|
||||
"scenic_surface_factory.h",
|
||||
"scenic_window.cc",
|
||||
"scenic_window.h",
|
||||
"scenic_window_canvas.cc",
|
||||
"scenic_window_canvas.h",
|
||||
"scenic_window_manager.cc",
|
||||
"scenic_window_manager.h",
|
||||
"sysmem_buffer_collection.cc",
|
||||
"sysmem_buffer_collection.h",
|
||||
"sysmem_buffer_manager.cc",
|
||||
"sysmem_buffer_manager.h",
|
||||
"sysmem_native_pixmap.cc",
|
||||
"sysmem_native_pixmap.h",
|
||||
"vulkan_implementation_scenic.cc",
|
||||
"vulkan_implementation_scenic.h",
|
||||
]
|
||||
|
||||
defines = [
|
||||
"OZONE_IMPLEMENTATION",
|
||||
"VK_USE_PLATFORM_FUCHSIA",
|
||||
"VK_USE_PLATFORM_MAGMA_KHR",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"//base",
|
||||
"//gpu/ipc/common:vulkan_ycbcr_info",
|
||||
"//mojo/public/cpp/system",
|
||||
"//services/service_manager/public/cpp",
|
||||
"//skia",
|
||||
"//third_party/angle/src/common/fuchsia_egl",
|
||||
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.element:fuchsia.element_hlcpp",
|
||||
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.images:fuchsia.images_hlcpp",
|
||||
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.mem:fuchsia.mem_hlcpp",
|
||||
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.sysmem:fuchsia.sysmem_hlcpp",
|
||||
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.pointer:fuchsia.ui.pointer_cpp_hlcpp_conversion",
|
||||
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.views:fuchsia.ui.views_cpp_hlcpp_conversion",
|
||||
"//third_party/fuchsia-sdk/sdk/pkg/component_incoming_cpp",
|
||||
"//third_party/fuchsia-sdk/sdk/pkg/scenic_cpp",
|
||||
"//third_party/fuchsia-sdk/sdk/pkg/sys_cpp",
|
||||
"//ui/base",
|
||||
"//ui/base/cursor",
|
||||
"//ui/base/ime/fuchsia",
|
||||
"//ui/events:dom_keycode_converter",
|
||||
"//ui/events/ozone/layout",
|
||||
"//ui/ozone:ozone_base",
|
||||
"//ui/ozone/common",
|
||||
"//ui/ozone/platform/scenic/mojom",
|
||||
]
|
||||
public_deps = [
|
||||
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.gfx:fuchsia.ui.gfx_hlcpp",
|
||||
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.input:fuchsia.ui.input_hlcpp",
|
||||
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.scenic:fuchsia.ui.scenic_hlcpp",
|
||||
"//ui/gfx/geometry",
|
||||
"//ui/platform_window",
|
||||
]
|
||||
|
||||
data_deps = [ "//third_party/fuchsia-sdk/sdk/pkg/vulkan" ]
|
||||
|
||||
# VulkanInstance enables validation layer in Debug builds and when DCHECKs
|
||||
# are enabled in Release builds. In these cases the validation layer
|
||||
# libraries and configs need to be included in the generated Fuchsia
|
||||
# package.
|
||||
if (is_debug || dcheck_always_on) {
|
||||
data_deps += [ "//third_party/fuchsia-sdk/sdk/pkg/vulkan_layers:VkLayer_khronos_validation" ]
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
include_rules = [
|
||||
"+gpu/ipc/common",
|
||||
"+mojo/public",
|
||||
"+third_party/angle/src/common/fuchsia_egl",
|
||||
"+third_party/skia/include",
|
||||
]
|
@ -1 +0,0 @@
|
||||
mixins: "//build/fuchsia/COMMON_METADATA"
|
@ -1 +0,0 @@
|
||||
file://build/fuchsia/OWNERS
|
@ -1,251 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// 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/client_native_pixmap_factory_scenic.h"
|
||||
|
||||
#include <lib/zx/vmar.h>
|
||||
#include <lib/zx/vmo.h>
|
||||
#include <vector>
|
||||
|
||||
#include "base/bits.h"
|
||||
#include "base/check_op.h"
|
||||
#include "base/fuchsia/fuchsia_logging.h"
|
||||
#include "base/fuchsia/koid.h"
|
||||
#include "base/numerics/safe_conversions.h"
|
||||
#include "base/system/sys_info.h"
|
||||
#include "ui/gfx/buffer_format_util.h"
|
||||
#include "ui/gfx/client_native_pixmap.h"
|
||||
#include "ui/gfx/client_native_pixmap_factory.h"
|
||||
#include "ui/gfx/native_pixmap_handle.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
namespace {
|
||||
|
||||
bool AlignUpToPageSizeChecked(size_t size, size_t* aligned_size) {
|
||||
static_assert(base::IsValueInRangeForNumericType<size_t>(ZX_PAGE_SIZE) &&
|
||||
base::bits::IsPowerOfTwo(ZX_PAGE_SIZE),
|
||||
"The page size must fit in a size_t and be a power of 2.");
|
||||
constexpr size_t kPageSizeMinusOne = ZX_PAGE_SIZE - 1;
|
||||
base::CheckedNumeric<size_t> aligned_size_checked =
|
||||
base::CheckAdd(size, kPageSizeMinusOne) & (~kPageSizeMinusOne);
|
||||
if (!aligned_size_checked.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
*aligned_size = aligned_size_checked.ValueOrDie();
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class ClientNativePixmapFuchsia : public gfx::ClientNativePixmap {
|
||||
public:
|
||||
explicit ClientNativePixmapFuchsia(gfx::NativePixmapHandle handle)
|
||||
: handle_(std::move(handle)) {}
|
||||
|
||||
ClientNativePixmapFuchsia(const ClientNativePixmapFuchsia&) = delete;
|
||||
ClientNativePixmapFuchsia& operator=(const ClientNativePixmapFuchsia&) =
|
||||
delete;
|
||||
|
||||
~ClientNativePixmapFuchsia() override {
|
||||
if (mapping_) {
|
||||
// Flush the cache if Unmap is not called before the pixmap is destroyed.
|
||||
if (logically_mapped_) {
|
||||
Unmap();
|
||||
}
|
||||
|
||||
zx_status_t status = zx::vmar::root_self()->unmap(
|
||||
reinterpret_cast<uintptr_t>(mapping_), mapping_size_);
|
||||
ZX_DCHECK(status == ZX_OK, status) << "zx_vmar_unmap";
|
||||
}
|
||||
}
|
||||
|
||||
bool Map() override {
|
||||
if (mapping_) {
|
||||
logically_mapped_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (handle_.planes.empty() || !handle_.planes[0].vmo) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Assume that the last plane is at the end of the VMO. If this assumption
|
||||
// is violated, we shouldn't get here because
|
||||
// ScenicClientNativePixmapFactory::ImportFromHandle() validates (through
|
||||
// CanFitImageForSizeAndFormat()) that the (offset + size) for each plane is
|
||||
// less than or equal to |last_plane_end|.
|
||||
//
|
||||
// Note: the |last_plane_end| computation has been determined to not
|
||||
// overflow in ScenicClientNativePixmapFactory::ImportFromHandle() (through
|
||||
// CanFitImageForSizeAndFormat()).
|
||||
const size_t last_plane_end =
|
||||
base::CheckAdd(handle_.planes.back().offset, handle_.planes.back().size)
|
||||
.ValueOrDie<size_t>();
|
||||
|
||||
#if DCHECK_IS_ON()
|
||||
// All planes should fall within the range that ends with the last plane.
|
||||
// This has been verified by
|
||||
// ScenicClientNativePixmapFactory::ImportFromHandle() (through
|
||||
// CanFitImageForSizeAndFormat()).
|
||||
for (auto& plane : handle_.planes) {
|
||||
DCHECK(base::CheckAdd(plane.offset, plane.size).ValueOrDie<size_t>() <=
|
||||
last_plane_end);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Round mapping size to align with the page size. Mapping
|
||||
// |aligned_mapping_size| bytes should be safe because
|
||||
// FlatlandClientNativePixmapFactory::ImportFromHandle() ensures that
|
||||
// |last_plane_end| <= <size of the VMO> where <size of the VMO> is
|
||||
// page_aligned which implies that |aligned_mapping_size| <= <size of the
|
||||
// VMO>.
|
||||
size_t aligned_mapping_size;
|
||||
if (!AlignUpToPageSizeChecked(last_plane_end, &aligned_mapping_size)) {
|
||||
return false;
|
||||
}
|
||||
mapping_size_ = aligned_mapping_size;
|
||||
|
||||
// Pre-commit the pages of the pixmap, since it is likely that every page
|
||||
// will be touched. This is also necessary to successfully pre-fill the page
|
||||
// table entries during the subsequent map operation.
|
||||
zx_status_t status = handle_.planes[0].vmo.op_range(
|
||||
ZX_VMO_OP_COMMIT, 0, mapping_size_, nullptr, 0);
|
||||
ZX_DCHECK(status == ZX_OK, status) << "zx_vmo_op_range";
|
||||
|
||||
// ZX_VM_MAP_RANGE pre-fills the page table entries for committed pages to
|
||||
// avoid unnecessary page faults.
|
||||
zx_vaddr_t addr;
|
||||
status = zx::vmar::root_self()->map(
|
||||
ZX_VM_PERM_READ | ZX_VM_PERM_WRITE | ZX_VM_MAP_RANGE, 0,
|
||||
handle_.planes[0].vmo, 0, mapping_size_, &addr);
|
||||
if (status != ZX_OK) {
|
||||
ZX_DLOG(ERROR, status) << "zx_vmar_map";
|
||||
return false;
|
||||
}
|
||||
mapping_ = reinterpret_cast<uint8_t*>(addr);
|
||||
logically_mapped_ = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Unmap() override {
|
||||
DCHECK(mapping_);
|
||||
DCHECK(logically_mapped_);
|
||||
|
||||
// Flush the CPu cache in case the GPU reads the data directly from RAM.
|
||||
// Keep the mapping to avoid unnecessary overhead when later reusing the
|
||||
// pixmap. The actual unmap happens when the pixmap is destroyed.
|
||||
if (handle_.ram_coherency) {
|
||||
zx_status_t status =
|
||||
zx_cache_flush(mapping_, mapping_size_,
|
||||
ZX_CACHE_FLUSH_DATA | ZX_CACHE_FLUSH_INVALIDATE);
|
||||
ZX_DCHECK(status == ZX_OK, status) << "zx_cache_flush";
|
||||
}
|
||||
logically_mapped_ = false;
|
||||
}
|
||||
|
||||
size_t GetNumberOfPlanes() const override { return handle_.planes.size(); }
|
||||
|
||||
void* GetMemoryAddress(size_t plane) const override {
|
||||
DCHECK_LT(plane, handle_.planes.size());
|
||||
DCHECK(mapping_);
|
||||
return mapping_ + handle_.planes[plane].offset;
|
||||
}
|
||||
|
||||
int GetStride(size_t plane) const override {
|
||||
DCHECK_LT(plane, handle_.planes.size());
|
||||
return base::checked_cast<int>(handle_.planes[plane].stride);
|
||||
}
|
||||
|
||||
gfx::NativePixmapHandle CloneHandleForIPC() const override {
|
||||
return gfx::CloneHandleForIPC(handle_);
|
||||
}
|
||||
|
||||
private:
|
||||
gfx::NativePixmapHandle handle_;
|
||||
|
||||
bool logically_mapped_ = false;
|
||||
uint8_t* mapping_ = nullptr;
|
||||
size_t mapping_size_ = 0;
|
||||
};
|
||||
|
||||
class ScenicClientNativePixmapFactory : public gfx::ClientNativePixmapFactory {
|
||||
public:
|
||||
ScenicClientNativePixmapFactory() = default;
|
||||
|
||||
ScenicClientNativePixmapFactory(const ScenicClientNativePixmapFactory&) =
|
||||
delete;
|
||||
ScenicClientNativePixmapFactory& operator=(
|
||||
const ScenicClientNativePixmapFactory&) = delete;
|
||||
|
||||
~ScenicClientNativePixmapFactory() override = default;
|
||||
|
||||
std::unique_ptr<gfx::ClientNativePixmap> ImportFromHandle(
|
||||
gfx::NativePixmapHandle handle,
|
||||
const gfx::Size& size,
|
||||
gfx::BufferFormat format,
|
||||
gfx::BufferUsage usage) override {
|
||||
// |planes| may be empty for non-mappable pixmaps. No need to validate the
|
||||
// handle in that case.
|
||||
if (handle.planes.empty()) {
|
||||
return std::make_unique<ClientNativePixmapFuchsia>(std::move(handle));
|
||||
}
|
||||
|
||||
// Validate that all planes refer to a single memory object.
|
||||
const absl::optional<zx_koid_t> first_plane_koid =
|
||||
base::GetKoid(handle.planes[0].vmo);
|
||||
if (!first_plane_koid) {
|
||||
return nullptr;
|
||||
}
|
||||
for (const auto& plane : handle.planes) {
|
||||
const absl::optional<zx_koid_t> plane_koid = base::GetKoid(plane.vmo);
|
||||
DCHECK(plane.vmo.is_valid() || !plane_koid);
|
||||
if (plane_koid != first_plane_koid) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (!CanFitImageForSizeAndFormat(handle, size, format,
|
||||
/*assume_single_memory_object=*/true)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// The |last_plane_end| computation should not overflow if the
|
||||
// CanFitImageForSizeAndFormat() check passed.
|
||||
const size_t last_plane_end =
|
||||
base::CheckAdd(handle.planes.back().offset, handle.planes.back().size)
|
||||
.ValueOrDie<size_t>();
|
||||
|
||||
uint64_t vmo_size;
|
||||
if (handle.planes.back().vmo.get_size(&vmo_size) != ZX_OK ||
|
||||
!base::IsValueInRangeForNumericType<size_t>(vmo_size) ||
|
||||
base::checked_cast<size_t>(vmo_size) < last_plane_end) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#if DCHECK_IS_ON()
|
||||
// zx_vmo_get_size() should return a page-aligned size. This is important
|
||||
// because we request a page-aligned size in
|
||||
// ClientNativePixmapFuchsia::Map().
|
||||
DCHECK_EQ(vmo_size % ZX_PAGE_SIZE, 0u);
|
||||
|
||||
// The CanFitImageForSizeAndFormat() call above should guarantee that the
|
||||
// (offset + size) for each plane is <= |last_plane_end|, and since we now
|
||||
// know that |last_plane_end| <= |vmo_size|, then (offset + size) for each
|
||||
// plane <= |vmo_size|.
|
||||
for (const auto& plane : handle.planes) {
|
||||
DCHECK_LE(plane.offset + plane.size, vmo_size);
|
||||
}
|
||||
#endif
|
||||
|
||||
return std::make_unique<ClientNativePixmapFuchsia>(std::move(handle));
|
||||
}
|
||||
};
|
||||
|
||||
gfx::ClientNativePixmapFactory* CreateClientNativePixmapFactoryScenic() {
|
||||
return new ScenicClientNativePixmapFactory();
|
||||
}
|
||||
|
||||
} // namespace ui
|
@ -1,20 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// 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_CLIENT_NATIVE_PIXMAP_FACTORY_SCENIC_H_
|
||||
#define UI_OZONE_PLATFORM_SCENIC_CLIENT_NATIVE_PIXMAP_FACTORY_SCENIC_H_
|
||||
|
||||
namespace gfx {
|
||||
class ClientNativePixmapFactory;
|
||||
} // namespace gfx
|
||||
|
||||
namespace ui {
|
||||
|
||||
// Scenic-platform constructor hook, for use by the auto-generated platform
|
||||
// constructor-list.
|
||||
gfx::ClientNativePixmapFactory* CreateClientNativePixmapFactoryScenic();
|
||||
|
||||
} // namespace ui
|
||||
|
||||
#endif // UI_OZONE_PLATFORM_SCENIC_CLIENT_NATIVE_PIXMAP_FACTORY_SCENIC_H_
|
@ -1,43 +0,0 @@
|
||||
// Copyright 2020 The Chromium Authors
|
||||
// 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/overlay_manager_scenic.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "ui/ozone/platform/scenic/sysmem_native_pixmap.h"
|
||||
#include "ui/ozone/public/overlay_candidates_ozone.h"
|
||||
|
||||
namespace ui {
|
||||
namespace {
|
||||
|
||||
class OverlayCandidatesScenic : public OverlayCandidatesOzone {
|
||||
public:
|
||||
OverlayCandidatesScenic() = default;
|
||||
|
||||
void CheckOverlaySupport(OverlaySurfaceCandidateList* candidates) override {
|
||||
for (auto& candidate : *candidates) {
|
||||
if (!candidate.native_pixmap)
|
||||
continue;
|
||||
SysmemNativePixmap* sysmem_native_pixmap =
|
||||
reinterpret_cast<SysmemNativePixmap*>(candidate.native_pixmap.get());
|
||||
candidate.overlay_handled = sysmem_native_pixmap->SupportsOverlayPlane();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
OverlayManagerScenic::OverlayManagerScenic() {
|
||||
// Fuchsia overlays rely on ShouldUseRealBuffersForPageFlipTest.
|
||||
allow_sync_and_real_buffer_page_flip_testing_ = true;
|
||||
}
|
||||
|
||||
OverlayManagerScenic::~OverlayManagerScenic() = default;
|
||||
|
||||
std::unique_ptr<OverlayCandidatesOzone>
|
||||
OverlayManagerScenic::CreateOverlayCandidates(gfx::AcceleratedWidget widget) {
|
||||
return std::make_unique<OverlayCandidatesScenic>();
|
||||
}
|
||||
|
||||
} // namespace ui
|
@ -1,29 +0,0 @@
|
||||
// Copyright 2020 The Chromium Authors
|
||||
// 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_OVERLAY_MANAGER_SCENIC_H_
|
||||
#define UI_OZONE_PLATFORM_SCENIC_OVERLAY_MANAGER_SCENIC_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "ui/ozone/public/overlay_manager_ozone.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
class OverlayManagerScenic : public OverlayManagerOzone {
|
||||
public:
|
||||
OverlayManagerScenic();
|
||||
~OverlayManagerScenic() override;
|
||||
|
||||
OverlayManagerScenic(const OverlayManagerScenic&) = delete;
|
||||
OverlayManagerScenic& operator=(const OverlayManagerScenic&) = delete;
|
||||
|
||||
// OverlayManagerOzone implementation
|
||||
std::unique_ptr<OverlayCandidatesOzone> CreateOverlayCandidates(
|
||||
gfx::AcceleratedWidget widget) override;
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
|
||||
#endif // UI_OZONE_PLATFORM_SCENIC_OVERLAY_MANAGER_SCENIC_H_
|
@ -1,271 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// 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/ozone_platform_scenic.h"
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <fidl/fuchsia.ui.views/cpp/hlcpp_conversion.h>
|
||||
#include <fuchsia/ui/views/cpp/fidl.h>
|
||||
#include <lib/ui/scenic/cpp/view_token_pair.h>
|
||||
|
||||
#include "base/check.h"
|
||||
#include "base/fuchsia/fuchsia_logging.h"
|
||||
#include "base/memory/ptr_util.h"
|
||||
#include "base/message_loop/message_pump_type.h"
|
||||
#include "base/no_destructor.h"
|
||||
#include "base/notreached.h"
|
||||
#include "base/task/current_thread.h"
|
||||
#include "base/task/single_thread_task_runner.h"
|
||||
#include "build/build_config.h"
|
||||
#include "mojo/public/cpp/bindings/pending_remote.h"
|
||||
#include "ui/base/cursor/cursor_factory.h"
|
||||
#include "ui/base/ime/fuchsia/input_method_fuchsia.h"
|
||||
#include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
|
||||
#include "ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h"
|
||||
#include "ui/events/platform/platform_event_source.h"
|
||||
#include "ui/gfx/native_widget_types.h"
|
||||
#include "ui/ozone/common/bitmap_cursor_factory.h"
|
||||
#include "ui/ozone/common/stub_overlay_manager.h"
|
||||
#include "ui/ozone/platform/scenic/mojom/scenic_gpu_service.mojom.h"
|
||||
#include "ui/ozone/platform/scenic/overlay_manager_scenic.h"
|
||||
#include "ui/ozone/platform/scenic/scenic_gpu_host.h"
|
||||
#include "ui/ozone/platform/scenic/scenic_gpu_service.h"
|
||||
#include "ui/ozone/platform/scenic/scenic_surface_factory.h"
|
||||
#include "ui/ozone/platform/scenic/scenic_window.h"
|
||||
#include "ui/ozone/platform/scenic/scenic_window_manager.h"
|
||||
#include "ui/ozone/platform/scenic/sysmem_buffer_collection.h"
|
||||
#include "ui/ozone/platform_selection.h"
|
||||
#include "ui/ozone/public/gpu_platform_support_host.h"
|
||||
#include "ui/ozone/public/input_controller.h"
|
||||
#include "ui/ozone/public/ozone_platform.h"
|
||||
#include "ui/ozone/public/ozone_switches.h"
|
||||
#include "ui/ozone/public/system_input_injector.h"
|
||||
#include "ui/platform_window/fuchsia/initialize_presenter_api_view.h"
|
||||
#include "ui/platform_window/platform_window_init_properties.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
namespace {
|
||||
|
||||
::fuchsia::ui::views::ViewRef CloneViewRef(
|
||||
const ::fuchsia::ui::views::ViewRef& view_ref) {
|
||||
::fuchsia::ui::views::ViewRef dup;
|
||||
zx_status_t status =
|
||||
view_ref.reference.duplicate(ZX_RIGHT_SAME_RIGHTS, &dup.reference);
|
||||
ZX_CHECK(status == ZX_OK, status) << "zx_object_duplicate";
|
||||
return dup;
|
||||
}
|
||||
|
||||
class ScenicPlatformEventSource : public ui::PlatformEventSource {
|
||||
public:
|
||||
ScenicPlatformEventSource() = default;
|
||||
|
||||
ScenicPlatformEventSource(const ScenicPlatformEventSource&) = delete;
|
||||
ScenicPlatformEventSource& operator=(const ScenicPlatformEventSource&) =
|
||||
delete;
|
||||
|
||||
~ScenicPlatformEventSource() override = default;
|
||||
};
|
||||
|
||||
// OzonePlatform for Scenic.
|
||||
class OzonePlatformScenic : public OzonePlatform,
|
||||
public base::CurrentThread::DestructionObserver {
|
||||
public:
|
||||
OzonePlatformScenic() = default;
|
||||
|
||||
OzonePlatformScenic(const OzonePlatformScenic&) = delete;
|
||||
OzonePlatformScenic& operator=(const OzonePlatformScenic&) = delete;
|
||||
|
||||
~OzonePlatformScenic() override = default;
|
||||
|
||||
// OzonePlatform implementation.
|
||||
ui::SurfaceFactoryOzone* GetSurfaceFactoryOzone() override {
|
||||
return surface_factory_.get();
|
||||
}
|
||||
|
||||
OverlayManagerOzone* GetOverlayManager() override {
|
||||
return overlay_manager_.get();
|
||||
}
|
||||
|
||||
CursorFactory* GetCursorFactory() override { return cursor_factory_.get(); }
|
||||
|
||||
InputController* GetInputController() override {
|
||||
return input_controller_.get();
|
||||
}
|
||||
|
||||
GpuPlatformSupportHost* GetGpuPlatformSupportHost() override {
|
||||
return scenic_gpu_host_.get();
|
||||
}
|
||||
|
||||
std::unique_ptr<SystemInputInjector> CreateSystemInputInjector() override {
|
||||
NOTIMPLEMENTED();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<PlatformWindow> CreatePlatformWindow(
|
||||
PlatformWindowDelegate* delegate,
|
||||
PlatformWindowInitProperties properties) override {
|
||||
BindInMainProcessIfNecessary();
|
||||
|
||||
if (!properties.view_token.value) {
|
||||
auto view_tokens = scenic::ViewTokenPair::New();
|
||||
properties.view_token = std::move(view_tokens.view_token);
|
||||
properties.view_ref_pair = scenic::ViewRefPair::New();
|
||||
properties.view_controller = ::ui::fuchsia::GetScenicViewPresenter().Run(
|
||||
std::move(view_tokens.view_holder_token),
|
||||
CloneViewRef(properties.view_ref_pair.view_ref));
|
||||
}
|
||||
|
||||
return std::make_unique<ScenicWindow>(window_manager_.get(), delegate,
|
||||
std::move(properties));
|
||||
}
|
||||
|
||||
const PlatformProperties& GetPlatformProperties() override {
|
||||
static base::NoDestructor<OzonePlatform::PlatformProperties> properties;
|
||||
static bool initialised = false;
|
||||
if (!initialised) {
|
||||
properties->message_pump_type_for_gpu = base::MessagePumpType::IO;
|
||||
properties->supports_vulkan_swap_chain = true;
|
||||
|
||||
initialised = true;
|
||||
}
|
||||
|
||||
return *properties;
|
||||
}
|
||||
|
||||
std::unique_ptr<display::NativeDisplayDelegate> CreateNativeDisplayDelegate()
|
||||
override {
|
||||
NOTIMPLEMENTED();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<PlatformScreen> CreateScreen() override {
|
||||
return window_manager_->CreateScreen();
|
||||
}
|
||||
|
||||
void InitScreen(PlatformScreen* screen) override {}
|
||||
|
||||
std::unique_ptr<InputMethod> CreateInputMethod(
|
||||
ImeKeyEventDispatcher* ime_key_event_dispatcher,
|
||||
gfx::AcceleratedWidget widget) override {
|
||||
return std::make_unique<InputMethodFuchsia>(
|
||||
window_manager_->GetWindow(widget)->is_virtual_keyboard_enabled(),
|
||||
ime_key_event_dispatcher,
|
||||
fidl::HLCPPToNatural(
|
||||
window_manager_->GetWindow(widget)->CloneViewRef()));
|
||||
}
|
||||
|
||||
bool InitializeUI(const InitParams& params) override {
|
||||
if (!PlatformEventSource::GetInstance())
|
||||
platform_event_source_ = std::make_unique<ScenicPlatformEventSource>();
|
||||
keyboard_layout_engine_ = std::make_unique<StubKeyboardLayoutEngine>();
|
||||
KeyboardLayoutEngineManager::SetKeyboardLayoutEngine(
|
||||
keyboard_layout_engine_.get());
|
||||
|
||||
window_manager_ = std::make_unique<ScenicWindowManager>();
|
||||
overlay_manager_ = std::make_unique<StubOverlayManager>();
|
||||
input_controller_ = CreateStubInputController();
|
||||
cursor_factory_ = std::make_unique<BitmapCursorFactory>();
|
||||
|
||||
scenic_gpu_host_ = std::make_unique<ScenicGpuHost>(window_manager_.get());
|
||||
|
||||
// SurfaceFactory is configured here to use a ui-process remote for software
|
||||
// output.
|
||||
if (!surface_factory_)
|
||||
surface_factory_ = std::make_unique<ScenicSurfaceFactory>();
|
||||
|
||||
if (base::SingleThreadTaskRunner::HasCurrentDefault())
|
||||
BindInMainProcessIfNecessary();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void InitializeGPU(const InitParams& params) override {
|
||||
DCHECK(!surface_factory_ || params.single_process);
|
||||
|
||||
if (!surface_factory_)
|
||||
surface_factory_ = std::make_unique<ScenicSurfaceFactory>();
|
||||
|
||||
if (!params.single_process) {
|
||||
mojo::PendingRemote<mojom::ScenicGpuHost> scenic_gpu_host_remote;
|
||||
scenic_gpu_service_ = std::make_unique<ScenicGpuService>(
|
||||
scenic_gpu_host_remote.InitWithNewPipeAndPassReceiver());
|
||||
|
||||
// SurfaceFactory is configured here to use a gpu-process remote. The
|
||||
// other end of the pipe will be attached through ScenicGpuService.
|
||||
surface_factory_->Initialize(std::move(scenic_gpu_host_remote));
|
||||
}
|
||||
|
||||
overlay_manager_ = std::make_unique<OverlayManagerScenic>();
|
||||
}
|
||||
|
||||
const PlatformRuntimeProperties& GetPlatformRuntimeProperties() override {
|
||||
static OzonePlatform::PlatformRuntimeProperties properties;
|
||||
properties.supports_native_pixmaps = true;
|
||||
properties.supports_overlays = true;
|
||||
return properties;
|
||||
}
|
||||
|
||||
void AddInterfaces(mojo::BinderMap* binders) override {
|
||||
binders->Add<mojom::ScenicGpuService>(
|
||||
scenic_gpu_service_->GetBinderCallback(),
|
||||
base::SingleThreadTaskRunner::GetCurrentDefault());
|
||||
}
|
||||
|
||||
bool IsNativePixmapConfigSupported(gfx::BufferFormat format,
|
||||
gfx::BufferUsage usage) const override {
|
||||
return SysmemBufferCollection::IsNativePixmapConfigSupported(format, usage);
|
||||
}
|
||||
|
||||
private:
|
||||
// Binds main process surface factory to main process ScenicGpuHost
|
||||
void BindInMainProcessIfNecessary() {
|
||||
if (bound_in_main_process_)
|
||||
return;
|
||||
|
||||
mojo::PendingRemote<mojom::ScenicGpuHost> gpu_host_remote;
|
||||
scenic_gpu_host_->Initialize(
|
||||
gpu_host_remote.InitWithNewPipeAndPassReceiver());
|
||||
surface_factory_->Initialize(std::move(gpu_host_remote));
|
||||
bound_in_main_process_ = true;
|
||||
|
||||
base::CurrentThread::Get()->AddDestructionObserver(this);
|
||||
}
|
||||
|
||||
void ShutdownInMainProcess() {
|
||||
DCHECK(bound_in_main_process_);
|
||||
surface_factory_->Shutdown();
|
||||
scenic_gpu_host_->Shutdown();
|
||||
window_manager_->Shutdown();
|
||||
bound_in_main_process_ = false;
|
||||
}
|
||||
|
||||
// base::CurrentThread::DestructionObserver implementation.
|
||||
void WillDestroyCurrentMessageLoop() override { ShutdownInMainProcess(); }
|
||||
|
||||
std::unique_ptr<ScenicWindowManager> window_manager_;
|
||||
|
||||
std::unique_ptr<KeyboardLayoutEngine> keyboard_layout_engine_;
|
||||
std::unique_ptr<PlatformEventSource> platform_event_source_;
|
||||
std::unique_ptr<CursorFactory> cursor_factory_;
|
||||
std::unique_ptr<InputController> input_controller_;
|
||||
std::unique_ptr<OverlayManagerOzone> overlay_manager_;
|
||||
std::unique_ptr<ScenicGpuHost> scenic_gpu_host_;
|
||||
std::unique_ptr<ScenicGpuService> scenic_gpu_service_;
|
||||
std::unique_ptr<ScenicSurfaceFactory> surface_factory_;
|
||||
|
||||
// Whether the main process has initialized mojo bindings.
|
||||
bool bound_in_main_process_ = false;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
OzonePlatform* CreateOzonePlatformScenic() {
|
||||
return new OzonePlatformScenic();
|
||||
}
|
||||
|
||||
} // namespace ui
|
@ -1,17 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// 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_OZONE_PLATFORM_SCENIC_H_
|
||||
#define UI_OZONE_PLATFORM_SCENIC_OZONE_PLATFORM_SCENIC_H_
|
||||
|
||||
namespace ui {
|
||||
|
||||
class OzonePlatform;
|
||||
|
||||
// Constructor hook for use in ozone_platform_list.cc
|
||||
OzonePlatform* CreateOzonePlatformScenic();
|
||||
|
||||
} // namespace ui
|
||||
|
||||
#endif // UI_OZONE_PLATFORM_SCENIC_OZONE_PLATFORM_SCENIC_H_
|
@ -1,60 +0,0 @@
|
||||
// Copyright 2021 The Chromium Authors
|
||||
// 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/safe_presenter.h"
|
||||
|
||||
#include <fuchsia/ui/gfx/cpp/fidl.h>
|
||||
#include <fuchsia/ui/scenic/cpp/fidl.h>
|
||||
|
||||
#include "base/check.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
SafePresenter::SafePresenter(scenic::Session* session) : session_(session) {
|
||||
DCHECK(session_);
|
||||
|
||||
session_->set_on_frame_presented_handler(
|
||||
fit::bind_member(this, &SafePresenter::OnFramePresented));
|
||||
}
|
||||
|
||||
SafePresenter::~SafePresenter() {
|
||||
// Clear the OnFramePresented callback, in case the `session_` outlives
|
||||
// SafePresenter.
|
||||
session_->set_on_frame_presented_handler({});
|
||||
}
|
||||
|
||||
void SafePresenter::QueuePresent() {
|
||||
// Present to Scenic immediately, if we can.
|
||||
if (presents_allowed_) {
|
||||
QueuePresentHelper();
|
||||
return;
|
||||
}
|
||||
|
||||
// We cannot present immediately, so queue for later.
|
||||
present_queued_ = true;
|
||||
}
|
||||
|
||||
void SafePresenter::QueuePresentHelper() {
|
||||
DCHECK(session_);
|
||||
DCHECK(presents_allowed_);
|
||||
|
||||
presents_allowed_ = false;
|
||||
present_queued_ = false;
|
||||
session_->Present2(/*requested_presentation_time=*/0,
|
||||
/*requested_prediction_span=*/0, [](auto) {});
|
||||
}
|
||||
|
||||
void SafePresenter::OnFramePresented(
|
||||
fuchsia::scenic::scheduling::FramePresentedInfo info) {
|
||||
presents_allowed_ = info.num_presents_allowed > 0;
|
||||
// Since we only have one Present2 call in progress at once, this must
|
||||
// be true.
|
||||
DCHECK(presents_allowed_);
|
||||
|
||||
if (present_queued_ && presents_allowed_) {
|
||||
QueuePresentHelper();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ui
|
@ -1,52 +0,0 @@
|
||||
// Copyright 2021 The Chromium Authors
|
||||
// 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_SAFE_PRESENTER_H_
|
||||
#define UI_OZONE_PLATFORM_SCENIC_SAFE_PRESENTER_H_
|
||||
|
||||
#include <lib/ui/scenic/cpp/session.h>
|
||||
|
||||
namespace ui {
|
||||
|
||||
using QueuePresentCallback = fit::function<void()>;
|
||||
|
||||
// Helper class used to call Present2() in fuchsia.ui.scenic.Session. By
|
||||
// limiting the number of Present2 calls, SafePresenter ensures that the Session
|
||||
// will not be shut down, thus, users of SafePresenter should not call Present2
|
||||
// on their own.
|
||||
//
|
||||
// More information can be found in the fuchsia.scenic.scheduling FIDL library,
|
||||
// in the prediction_info.fidl file.
|
||||
class SafePresenter {
|
||||
public:
|
||||
explicit SafePresenter(scenic::Session* session);
|
||||
~SafePresenter();
|
||||
|
||||
SafePresenter(const SafePresenter&) = delete;
|
||||
SafePresenter& operator=(const SafePresenter&) = delete;
|
||||
|
||||
// If possible, QueuePresent() immediately presents to the underlying Session.
|
||||
// If the maximum amount of pending Present2()s has been reached,
|
||||
// SafePresenter presents at the next earliest possible time. QueuePresent()
|
||||
// ensures that callbacks get processed in FIFO order.
|
||||
void QueuePresent();
|
||||
|
||||
private:
|
||||
void QueuePresentHelper();
|
||||
void OnFramePresented(fuchsia::scenic::scheduling::FramePresentedInfo info);
|
||||
|
||||
scenic::Session* const session_ = nullptr;
|
||||
|
||||
// |presents_allowed_| is true if Scenic allows at least one more Present2()
|
||||
// call. Scenic ensures a session will have a Present2 budget of at least 1 to
|
||||
// begin with.
|
||||
bool presents_allowed_ = true;
|
||||
|
||||
// |present_queued_| is true if there are unhandled QueuePresent() calls.
|
||||
bool present_queued_ = false;
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
|
||||
#endif // UI_OZONE_PLATFORM_SCENIC_SAFE_PRESENTER_H_
|
@ -1,94 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// 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_gpu_host.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <utility>
|
||||
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/functional/callback.h"
|
||||
#include "base/task/single_thread_task_runner.h"
|
||||
#include "mojo/public/cpp/system/message_pipe.h"
|
||||
#include "ui/ozone/platform/scenic/mojom/scenic_gpu_host.mojom.h"
|
||||
#include "ui/ozone/platform/scenic/mojom/scenic_gpu_service.mojom.h"
|
||||
#include "ui/ozone/platform/scenic/scenic_window.h"
|
||||
#include "ui/ozone/platform/scenic/scenic_window_manager.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using BinderCallback =
|
||||
base::RepeatingCallback<void(const std::string&,
|
||||
mojo::ScopedMessagePipeHandle)>;
|
||||
|
||||
template <typename Interface>
|
||||
void BindInterface(mojo::PendingReceiver<Interface> receiver,
|
||||
const BinderCallback& binder_callback) {
|
||||
binder_callback.Run(Interface::Name_, receiver.PassPipe());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace ui {
|
||||
|
||||
ScenicGpuHost::ScenicGpuHost(ScenicWindowManager* scenic_window_manager)
|
||||
: scenic_window_manager_(scenic_window_manager) {
|
||||
DETACH_FROM_THREAD(io_thread_checker_);
|
||||
}
|
||||
|
||||
ScenicGpuHost::~ScenicGpuHost() {
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
void ScenicGpuHost::Initialize(
|
||||
mojo::PendingReceiver<mojom::ScenicGpuHost> host_receiver) {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_);
|
||||
|
||||
DCHECK(!ui_thread_runner_);
|
||||
ui_thread_runner_ = base::SingleThreadTaskRunner::GetCurrentDefault();
|
||||
DCHECK(ui_thread_runner_);
|
||||
|
||||
host_receiver_.Bind(std::move(host_receiver));
|
||||
}
|
||||
|
||||
void ScenicGpuHost::Shutdown() {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_);
|
||||
|
||||
ui_thread_runner_ = nullptr;
|
||||
host_receiver_.reset();
|
||||
gpu_receiver_.reset();
|
||||
gpu_service_.reset();
|
||||
}
|
||||
|
||||
void ScenicGpuHost::AttachSurfaceToWindow(
|
||||
int32_t window_id,
|
||||
mojo::PlatformHandle surface_view_holder_token_mojo) {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_);
|
||||
ScenicWindow* scenic_window = scenic_window_manager_->GetWindow(window_id);
|
||||
if (!scenic_window)
|
||||
return;
|
||||
fuchsia::ui::views::ViewHolderToken surface_view_holder_token;
|
||||
surface_view_holder_token.value =
|
||||
zx::eventpair(surface_view_holder_token_mojo.TakeHandle());
|
||||
scenic_window->AttachSurfaceView(std::move(surface_view_holder_token));
|
||||
}
|
||||
|
||||
void ScenicGpuHost::OnChannelDestroyed(int host_id) {}
|
||||
|
||||
void ScenicGpuHost::OnGpuServiceLaunched(
|
||||
int host_id,
|
||||
GpuHostBindInterfaceCallback binder,
|
||||
GpuHostTerminateCallback terminate_callback) {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_);
|
||||
mojo::PendingRemote<mojom::ScenicGpuService> scenic_gpu_service;
|
||||
BindInterface(scenic_gpu_service.InitWithNewPipeAndPassReceiver(), binder);
|
||||
|
||||
gpu_receiver_.reset();
|
||||
gpu_service_.reset();
|
||||
|
||||
gpu_service_.Bind(std::move(scenic_gpu_service));
|
||||
gpu_service_->Initialize(gpu_receiver_.BindNewPipeAndPassRemote());
|
||||
}
|
||||
|
||||
} // namespace ui
|
@ -1,79 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// 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_GPU_HOST_H_
|
||||
#define UI_OZONE_PLATFORM_SCENIC_SCENIC_GPU_HOST_H_
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "base/functional/callback.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/task/single_thread_task_runner.h"
|
||||
#include "base/threading/thread_checker.h"
|
||||
#include "mojo/public/cpp/bindings/pending_receiver.h"
|
||||
#include "mojo/public/cpp/bindings/pending_remote.h"
|
||||
#include "mojo/public/cpp/bindings/receiver.h"
|
||||
#include "mojo/public/cpp/bindings/remote.h"
|
||||
#include "ui/ozone/platform/scenic/mojom/scenic_gpu_host.mojom.h"
|
||||
#include "ui/ozone/platform/scenic/mojom/scenic_gpu_service.mojom.h"
|
||||
#include "ui/ozone/public/gpu_platform_support_host.h"
|
||||
|
||||
namespace ui {
|
||||
class ScenicWindowManager;
|
||||
|
||||
// Browser process object which supports a GPU process host.
|
||||
//
|
||||
// Once a GPU process starts, this objects binds to it over mojo and
|
||||
// enables exchange of Scenic resources with it. In particular, we must
|
||||
// exchange export tokens for each view surface, so that the surface can
|
||||
// present to Scenic views managed by the browser.
|
||||
class ScenicGpuHost : public mojom::ScenicGpuHost,
|
||||
public GpuPlatformSupportHost {
|
||||
public:
|
||||
ScenicGpuHost(ScenicWindowManager* scenic_window_manager);
|
||||
|
||||
ScenicGpuHost(const ScenicGpuHost&) = delete;
|
||||
ScenicGpuHost& operator=(const ScenicGpuHost&) = delete;
|
||||
|
||||
~ScenicGpuHost() override;
|
||||
|
||||
// Binds the receiver for the main process surface factory.
|
||||
void Initialize(mojo::PendingReceiver<mojom::ScenicGpuHost> pending_receiver);
|
||||
|
||||
// Shuts down mojo service. After calling shutdown, it's safe to call
|
||||
// Initialize() again.
|
||||
void Shutdown();
|
||||
|
||||
// mojom::ScenicGpuHost:
|
||||
void AttachSurfaceToWindow(
|
||||
int32_t window_id,
|
||||
mojo::PlatformHandle surface_view_holder_token_mojo) override;
|
||||
|
||||
// GpuPlatformSupportHost:
|
||||
void OnChannelDestroyed(int host_id) override;
|
||||
void OnGpuServiceLaunched(
|
||||
int host_id,
|
||||
GpuHostBindInterfaceCallback binder,
|
||||
GpuHostTerminateCallback terminate_callback) override;
|
||||
|
||||
private:
|
||||
void UpdateReceiver(uint32_t service_launch_count,
|
||||
mojo::PendingReceiver<mojom::ScenicGpuHost> receiver);
|
||||
|
||||
ScenicWindowManager* const scenic_window_manager_;
|
||||
mojo::Receiver<mojom::ScenicGpuHost> host_receiver_{this};
|
||||
mojo::Receiver<mojom::ScenicGpuHost> gpu_receiver_{this};
|
||||
|
||||
mojo::Remote<mojom::ScenicGpuService> gpu_service_;
|
||||
scoped_refptr<base::SingleThreadTaskRunner> ui_thread_runner_;
|
||||
|
||||
THREAD_CHECKER(ui_thread_checker_);
|
||||
THREAD_CHECKER(io_thread_checker_);
|
||||
|
||||
base::WeakPtrFactory<ScenicGpuHost> weak_ptr_factory_{this};
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
|
||||
#endif // UI_OZONE_PLATFORM_SCENIC_SCENIC_GPU_HOST_H_
|
@ -1,42 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// 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_gpu_service.h"
|
||||
|
||||
#include "base/functional/bind.h"
|
||||
#include "mojo/public/c/system/message_pipe.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
ScenicGpuService::ScenicGpuService(
|
||||
mojo::PendingReceiver<mojom::ScenicGpuHost> gpu_host_receiver)
|
||||
: gpu_host_receiver_(std::move(gpu_host_receiver)) {}
|
||||
|
||||
ScenicGpuService::~ScenicGpuService() {}
|
||||
|
||||
base::RepeatingCallback<void(mojo::PendingReceiver<mojom::ScenicGpuService>)>
|
||||
ScenicGpuService::GetBinderCallback() {
|
||||
return base::BindRepeating(&ScenicGpuService::AddReceiver,
|
||||
weak_ptr_factory_.GetWeakPtr());
|
||||
}
|
||||
|
||||
void ScenicGpuService::Initialize(
|
||||
mojo::PendingRemote<mojom::ScenicGpuHost> gpu_host) {
|
||||
// The ScenicGpuService acts as a bridge to bind the
|
||||
// Remote<mojom::ScenicGpuHost>, owned by ScenicSurfaceFactory and
|
||||
// received in the constructor, and the mojo::Receiver<mojom::ScenicGpuHost>,
|
||||
// owned by ScenicGpuHost and received as a parameter in this function. Using
|
||||
// mojo::FusePipes is the only way to "bind" a pending remote with a
|
||||
// pending receiver.
|
||||
bool result =
|
||||
mojo::FusePipes(std::move(gpu_host_receiver_), std::move(gpu_host));
|
||||
DCHECK(result);
|
||||
}
|
||||
|
||||
void ScenicGpuService::AddReceiver(
|
||||
mojo::PendingReceiver<mojom::ScenicGpuService> receiver) {
|
||||
receiver_set_.Add(this, std::move(receiver));
|
||||
}
|
||||
|
||||
} // namespace ui
|
@ -1,52 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// 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_GPU_SERVICE_H_
|
||||
#define UI_OZONE_PLATFORM_SCENIC_SCENIC_GPU_SERVICE_H_
|
||||
|
||||
#include "base/functional/callback.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "mojo/public/cpp/bindings/pending_receiver.h"
|
||||
#include "mojo/public/cpp/bindings/pending_remote.h"
|
||||
#include "mojo/public/cpp/bindings/receiver_set.h"
|
||||
#include "ui/ozone/platform/scenic/mojom/scenic_gpu_host.mojom.h"
|
||||
#include "ui/ozone/platform/scenic/mojom/scenic_gpu_service.mojom.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
// GPU process service that enables presentation to Scenic.
|
||||
//
|
||||
// This object exposes a mojo service to the browser process from the GPU
|
||||
// process. The browser binds it to enable exchange of Scenic resources.
|
||||
// In particular, we must exchange export tokens for each view surface,
|
||||
// so that surfaces can present to Scenic views managed by the browser.
|
||||
class ScenicGpuService : public mojom::ScenicGpuService {
|
||||
public:
|
||||
ScenicGpuService(
|
||||
mojo::PendingReceiver<mojom::ScenicGpuHost> gpu_host_receiver);
|
||||
|
||||
ScenicGpuService(const ScenicGpuService&) = delete;
|
||||
ScenicGpuService& operator=(const ScenicGpuService&) = delete;
|
||||
|
||||
~ScenicGpuService() override;
|
||||
|
||||
base::RepeatingCallback<void(mojo::PendingReceiver<mojom::ScenicGpuService>)>
|
||||
GetBinderCallback();
|
||||
|
||||
// mojom::ScenicGpuService:
|
||||
void Initialize(mojo::PendingRemote<mojom::ScenicGpuHost> gpu_host) override;
|
||||
|
||||
private:
|
||||
void AddReceiver(mojo::PendingReceiver<mojom::ScenicGpuService> receiver);
|
||||
|
||||
mojo::PendingReceiver<mojom::ScenicGpuHost> gpu_host_receiver_;
|
||||
|
||||
mojo::ReceiverSet<mojom::ScenicGpuService> receiver_set_;
|
||||
|
||||
base::WeakPtrFactory<ScenicGpuService> weak_ptr_factory_{this};
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
|
||||
#endif // UI_OZONE_PLATFORM_SCENIC_SCENIC_GPU_SERVICE_H_
|
@ -1,114 +0,0 @@
|
||||
// Copyright 2020 The Chromium Authors
|
||||
// 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_overlay_view.h"
|
||||
|
||||
#include <lib/ui/scenic/cpp/commands.h>
|
||||
|
||||
#include "base/fuchsia/fuchsia_logging.h"
|
||||
#include "base/location.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
namespace {
|
||||
|
||||
// |buffer_collection_id| that is passed to ImagePipe::AddBufferCollection() if
|
||||
// SysmemBufferCollection instance is registered with one.
|
||||
static const uint32_t kImagePipeBufferCollectionId = 1;
|
||||
static const std::string kSessionDebugName = "chromium scenic overlay";
|
||||
|
||||
} // namespace
|
||||
|
||||
ScenicOverlayView::ScenicOverlayView(
|
||||
scenic::SessionPtrAndListenerRequest session_and_listener_request)
|
||||
: scenic_session_(std::move(session_and_listener_request)),
|
||||
safe_presenter_(&scenic_session_),
|
||||
image_material_(&scenic_session_) {
|
||||
scenic_session_.SetDebugName(kSessionDebugName);
|
||||
scenic_session_.set_error_handler(
|
||||
base::LogFidlErrorAndExitProcess(FROM_HERE, "ScenicSession"));
|
||||
}
|
||||
|
||||
ScenicOverlayView::~ScenicOverlayView() {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
|
||||
// Releasing |image_pipe_| implicitly also enforces cleanup.
|
||||
image_pipe_->RemoveBufferCollection(kImagePipeBufferCollectionId);
|
||||
}
|
||||
|
||||
void ScenicOverlayView::Initialize(
|
||||
fidl::InterfaceHandle<fuchsia::sysmem::BufferCollectionToken>
|
||||
collection_token) {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
|
||||
uint32_t image_pipe_id = scenic_session_.AllocResourceId();
|
||||
scenic_session_.Enqueue(
|
||||
scenic::NewCreateImagePipe2Cmd(image_pipe_id, image_pipe_.NewRequest()));
|
||||
image_pipe_.set_error_handler(
|
||||
base::LogFidlErrorAndExitProcess(FROM_HERE, "ImagePipe"));
|
||||
|
||||
image_material_.SetTexture(image_pipe_id);
|
||||
safe_presenter_.QueuePresent();
|
||||
|
||||
// Since there is one ImagePipe for each BufferCollection, it is ok to use a
|
||||
// fixed buffer_collection_id.
|
||||
// TODO(emircan): Consider using one ImagePipe per video decoder instead.
|
||||
image_pipe_->AddBufferCollection(kImagePipeBufferCollectionId,
|
||||
std::move(collection_token));
|
||||
}
|
||||
|
||||
uint32_t ScenicOverlayView::AddImage(uint32_t buffer_index,
|
||||
const gfx::Size& size) {
|
||||
uint32_t id = next_image_id_++;
|
||||
fuchsia::sysmem::ImageFormat_2 image_format = {};
|
||||
image_format.coded_width = size.width();
|
||||
image_format.coded_height = size.height();
|
||||
image_pipe_->AddImage(id, kImagePipeBufferCollectionId, buffer_index,
|
||||
image_format);
|
||||
return id;
|
||||
}
|
||||
|
||||
void ScenicOverlayView::RemoveImage(uint32_t image_id) {
|
||||
image_pipe_->RemoveImage(image_id);
|
||||
}
|
||||
|
||||
bool ScenicOverlayView::PresentImage(uint32_t image_id,
|
||||
std::vector<zx::event> acquire_fences,
|
||||
std::vector<zx::event> release_fences) {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
|
||||
image_pipe_->PresentImage(image_id, zx_clock_get_monotonic(),
|
||||
std::move(acquire_fences),
|
||||
std::move(release_fences), [](auto) {});
|
||||
return true;
|
||||
}
|
||||
|
||||
void ScenicOverlayView::SetBlendMode(bool enable_blend) {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
|
||||
if (enable_blend_ == enable_blend)
|
||||
return;
|
||||
|
||||
enable_blend_ = enable_blend;
|
||||
// Setting alpha as |255| marks the image as opaque and no content below would
|
||||
// be seen. Anything lower than 255 allows blending.
|
||||
image_material_.SetColor(255, 255, 255, enable_blend ? 254 : 255);
|
||||
safe_presenter_.QueuePresent();
|
||||
}
|
||||
|
||||
void ScenicOverlayView::AttachToScenicSurface(
|
||||
fuchsia::ui::views::ViewToken view_token) {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
|
||||
view_.emplace(&scenic_session_, std::move(view_token), kSessionDebugName);
|
||||
|
||||
scenic::ShapeNode shape(&scenic_session_);
|
||||
shape.SetShape(scenic::Rectangle(&scenic_session_, 1.f, 1.f));
|
||||
shape.SetMaterial(image_material_);
|
||||
|
||||
view_->AddChild(shape);
|
||||
safe_presenter_.QueuePresent();
|
||||
}
|
||||
|
||||
} // namespace ui
|
@ -1,75 +0,0 @@
|
||||
// Copyright 2020 The Chromium Authors
|
||||
// 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_OVERLAY_VIEW_H_
|
||||
#define UI_OZONE_PLATFORM_SCENIC_SCENIC_OVERLAY_VIEW_H_
|
||||
|
||||
#include <fuchsia/ui/scenic/cpp/fidl.h>
|
||||
#include <lib/ui/scenic/cpp/resources.h>
|
||||
#include <lib/ui/scenic/cpp/session.h>
|
||||
|
||||
#include "base/threading/thread_checker.h"
|
||||
#include "ui/gfx/geometry/size.h"
|
||||
#include "ui/ozone/platform/scenic/safe_presenter.h"
|
||||
#include "ui/ozone/platform/scenic/scenic_surface.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
// Holder for scenic::Session and scenic::View that owns an Image Pipe.
|
||||
//
|
||||
// This class allows the callers to access an ImagePipe and a scenic::View that
|
||||
// displays only that ImagePipe. This is used inside SysmemBufferCollection
|
||||
// instances to display overlays.
|
||||
class ScenicOverlayView {
|
||||
public:
|
||||
explicit ScenicOverlayView(
|
||||
scenic::SessionPtrAndListenerRequest session_and_listener_request);
|
||||
~ScenicOverlayView();
|
||||
ScenicOverlayView(const ScenicOverlayView&) = delete;
|
||||
ScenicOverlayView& operator=(const ScenicOverlayView&) = delete;
|
||||
|
||||
// Calls ImagePipe2::AddBufferCollection() using |collection_token|. All
|
||||
// |image_pipe| interactions in this class is then associated with this
|
||||
// BufferCollection.
|
||||
void Initialize(fidl::InterfaceHandle<fuchsia::sysmem::BufferCollectionToken>
|
||||
collection_token);
|
||||
|
||||
// Adds an image to the ImagePipe using the specified `buffer_index` and
|
||||
// `size`. Returns a non-zero `image_id` that may be used in `PresentImage()`
|
||||
// and `RemoveImage()`.
|
||||
uint32_t AddImage(uint32_t buffer_index, const gfx::Size& size);
|
||||
|
||||
// Removes image with the `image_id_` from the ImagePipe.
|
||||
void RemoveImage(uint32_t image_id);
|
||||
|
||||
// Calls `ImagePipe2::PresentImage()` on `image_pipe_` for the `image_id`
|
||||
// corresponding to |buffer_index| from the initialized BufferCollection.
|
||||
bool PresentImage(uint32_t image_id,
|
||||
std::vector<zx::event> acquire_fences,
|
||||
std::vector<zx::event> release_fences);
|
||||
|
||||
// If |enable_blend| is true, sets |image_pipe_| as non-opaque.
|
||||
void SetBlendMode(bool enable_blend);
|
||||
|
||||
// Attaches the view using the specified token.
|
||||
void AttachToScenicSurface(fuchsia::ui::views::ViewToken view_token);
|
||||
|
||||
private:
|
||||
scenic::Session scenic_session_;
|
||||
// Used for safely queueing Present() operations on |scenic_session_|.
|
||||
SafePresenter safe_presenter_;
|
||||
absl::optional<scenic::View> view_;
|
||||
fuchsia::images::ImagePipe2Ptr image_pipe_;
|
||||
scenic::Material image_material_;
|
||||
|
||||
uint32_t next_image_id_ = 1;
|
||||
|
||||
bool enable_blend_ = false;
|
||||
|
||||
THREAD_CHECKER(thread_checker_);
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
|
||||
#endif // UI_OZONE_PLATFORM_SCENIC_SCENIC_OVERLAY_VIEW_H_
|
@ -1,57 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// 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_screen.h"
|
||||
|
||||
#include "base/notreached.h"
|
||||
#include "ui/display/display.h"
|
||||
#include "ui/display/display_observer.h"
|
||||
#include "ui/gfx/geometry/point.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
ScenicScreen::ScenicScreen()
|
||||
: displays_({display::Display::GetDefaultDisplay()}) {}
|
||||
|
||||
ScenicScreen::~ScenicScreen() = default;
|
||||
|
||||
const std::vector<display::Display>& ScenicScreen::GetAllDisplays() const {
|
||||
return displays_;
|
||||
}
|
||||
|
||||
display::Display ScenicScreen::GetPrimaryDisplay() const {
|
||||
return displays_[0];
|
||||
}
|
||||
|
||||
display::Display ScenicScreen::GetDisplayForAcceleratedWidget(
|
||||
gfx::AcceleratedWidget widget) const {
|
||||
return displays_[0];
|
||||
}
|
||||
|
||||
gfx::Point ScenicScreen::GetCursorScreenPoint() const {
|
||||
NOTIMPLEMENTED_LOG_ONCE();
|
||||
return gfx::Point();
|
||||
}
|
||||
|
||||
gfx::AcceleratedWidget ScenicScreen::GetAcceleratedWidgetAtScreenPoint(
|
||||
const gfx::Point& point) const {
|
||||
NOTIMPLEMENTED_LOG_ONCE();
|
||||
return gfx::kNullAcceleratedWidget;
|
||||
}
|
||||
|
||||
display::Display ScenicScreen::GetDisplayNearestPoint(
|
||||
const gfx::Point& point) const {
|
||||
return displays_[0];
|
||||
}
|
||||
|
||||
display::Display ScenicScreen::GetDisplayMatching(
|
||||
const gfx::Rect& match_rect) const {
|
||||
return displays_[0];
|
||||
}
|
||||
|
||||
void ScenicScreen::AddObserver(display::DisplayObserver* observer) {}
|
||||
|
||||
void ScenicScreen::RemoveObserver(display::DisplayObserver* observer) {}
|
||||
|
||||
} // namespace ui
|
@ -1,48 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// 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_SCREEN_H_
|
||||
#define UI_OZONE_PLATFORM_SCENIC_SCENIC_SCREEN_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/observer_list.h"
|
||||
#include "ui/ozone/public/ozone_platform.h"
|
||||
#include "ui/ozone/public/platform_screen.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
// A PlatformScreen implementation for Scenic.
|
||||
class ScenicScreen : public PlatformScreen {
|
||||
public:
|
||||
ScenicScreen();
|
||||
|
||||
ScenicScreen(const ScenicScreen&) = delete;
|
||||
ScenicScreen& operator=(const ScenicScreen&) = delete;
|
||||
|
||||
~ScenicScreen() override;
|
||||
|
||||
// display::Screen implementation.
|
||||
const std::vector<display::Display>& GetAllDisplays() const override;
|
||||
display::Display GetPrimaryDisplay() const override;
|
||||
display::Display GetDisplayForAcceleratedWidget(
|
||||
gfx::AcceleratedWidget widget) const override;
|
||||
gfx::Point GetCursorScreenPoint() const override;
|
||||
gfx::AcceleratedWidget GetAcceleratedWidgetAtScreenPoint(
|
||||
const gfx::Point& point) const override;
|
||||
display::Display GetDisplayNearestPoint(
|
||||
const gfx::Point& point) const override;
|
||||
display::Display GetDisplayMatching(
|
||||
const gfx::Rect& match_rect) const override;
|
||||
void AddObserver(display::DisplayObserver* observer) override;
|
||||
void RemoveObserver(display::DisplayObserver* observer) override;
|
||||
|
||||
private:
|
||||
std::vector<display::Display> displays_;
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
|
||||
#endif // UI_OZONE_PLATFORM_SCENIC_SCENIC_SCREEN_H_
|
@ -1,608 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// 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_surface.h"
|
||||
|
||||
#include <lib/sys/cpp/component_context.h>
|
||||
#include <lib/ui/scenic/cpp/commands.h>
|
||||
#include <lib/ui/scenic/cpp/view_token_pair.h>
|
||||
#include <lib/zx/eventpair.h>
|
||||
#include <zircon/types.h>
|
||||
|
||||
#include "base/fuchsia/fuchsia_logging.h"
|
||||
#include "base/fuchsia/koid.h"
|
||||
#include "base/fuchsia/process_context.h"
|
||||
#include "base/numerics/math_constants.h"
|
||||
#include "base/process/process_handle.h"
|
||||
#include "base/trace_event/trace_event.h"
|
||||
#include "gpu/vulkan/vulkan_device_queue.h"
|
||||
#include "sysmem_native_pixmap.h"
|
||||
#include "ui/gfx/buffer_types.h"
|
||||
#include "ui/gfx/geometry/rect_conversions.h"
|
||||
#include "ui/ozone/platform/scenic/scenic_gpu_host.h"
|
||||
#include "ui/ozone/platform/scenic/scenic_surface_factory.h"
|
||||
#include "ui/ozone/platform/scenic/sysmem_buffer_collection.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
namespace {
|
||||
|
||||
// Scenic has z-fighting problems in 3D API, so we add tiny z plane increments
|
||||
// to elevate content. ViewProperties set by ScenicWindow sets z-plane to
|
||||
// [-0.5f, 0.5f] range, so 0.01f is small enough to make a difference.
|
||||
constexpr float kElevationStep = 0.01f;
|
||||
|
||||
std::vector<zx::event> GpuFenceHandlesToZxEvents(
|
||||
std::vector<gfx::GpuFenceHandle> handles) {
|
||||
std::vector<zx::event> events;
|
||||
events.reserve(handles.size());
|
||||
for (auto& handle : handles)
|
||||
events.push_back(std::move(handle.owned_event));
|
||||
return events;
|
||||
}
|
||||
|
||||
zx::event DuplicateZxEvent(const zx::event& event) {
|
||||
zx::event result;
|
||||
zx_status_t status = event.duplicate(ZX_RIGHT_SAME_RIGHTS, &result);
|
||||
ZX_DCHECK(status == ZX_OK, status);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<gfx::GpuFence> DuplicateGpuFences(
|
||||
const std::vector<gfx::GpuFenceHandle>& fence_handles) {
|
||||
std::vector<gfx::GpuFence> fences;
|
||||
fences.reserve(fence_handles.size());
|
||||
for (const auto& handle : fence_handles)
|
||||
fences.emplace_back(handle.Clone());
|
||||
return fences;
|
||||
}
|
||||
|
||||
// Converts OverlayTransform enum to angle in radians.
|
||||
float OverlayTransformToRadians(gfx::OverlayTransform plane_transform) {
|
||||
switch (plane_transform) {
|
||||
case gfx::OVERLAY_TRANSFORM_NONE:
|
||||
case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL:
|
||||
case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL:
|
||||
return 0;
|
||||
case gfx::OVERLAY_TRANSFORM_ROTATE_90:
|
||||
return base::kPiFloat * .5f;
|
||||
case gfx::OVERLAY_TRANSFORM_ROTATE_180:
|
||||
return base::kPiFloat;
|
||||
case gfx::OVERLAY_TRANSFORM_ROTATE_270:
|
||||
return base::kPiFloat * 1.5f;
|
||||
case gfx::OVERLAY_TRANSFORM_INVALID:
|
||||
NOTREACHED();
|
||||
return 0;
|
||||
}
|
||||
NOTREACHED();
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ScenicSurface::ScenicSurface(
|
||||
ScenicSurfaceFactory* scenic_surface_factory,
|
||||
SysmemBufferManager* sysmem_buffer_manager,
|
||||
gfx::AcceleratedWidget window,
|
||||
scenic::SessionPtrAndListenerRequest sesion_and_listener_request)
|
||||
: scenic_session_(std::move(sesion_and_listener_request)),
|
||||
safe_presenter_(&scenic_session_),
|
||||
main_shape_(&scenic_session_),
|
||||
main_material_(&scenic_session_),
|
||||
scenic_surface_factory_(scenic_surface_factory),
|
||||
sysmem_buffer_manager_(sysmem_buffer_manager),
|
||||
window_(window) {
|
||||
// Setting alpha to 0 makes this transparent.
|
||||
scenic::Material transparent_material(&scenic_session_);
|
||||
transparent_material.SetColor(0, 0, 0, 0);
|
||||
main_shape_.SetShape(scenic::Rectangle(&scenic_session_, 1.f, 1.f));
|
||||
main_shape_.SetMaterial(transparent_material);
|
||||
main_shape_.SetEventMask(fuchsia::ui::gfx::kMetricsEventMask);
|
||||
scenic_surface_factory->AddSurface(window, this);
|
||||
scenic_session_.SetDebugName("Chromium ScenicSurface");
|
||||
scenic_session_.set_event_handler(
|
||||
fit::bind_member(this, &ScenicSurface::OnScenicEvents));
|
||||
}
|
||||
|
||||
ScenicSurface::~ScenicSurface() {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
|
||||
// Signal release fences that were submitted in the last PresentImage(). This
|
||||
// is necessary because ExternalVkImageBacking destructor will wait for the
|
||||
// corresponding semaphores, while they may not be signaled by the ImagePipe.
|
||||
for (auto& fence : release_fences_from_last_present_) {
|
||||
auto status =
|
||||
fence.signal(/*clear_mask=*/0, /*set_mask=*/ZX_EVENT_SIGNALED);
|
||||
ZX_DCHECK(status == ZX_OK, status);
|
||||
}
|
||||
|
||||
scenic_surface_factory_->RemoveSurface(window_);
|
||||
}
|
||||
|
||||
ScenicSurface::OverlayViewInfo::OverlayViewInfo(
|
||||
scenic::Session* scenic_session,
|
||||
fuchsia::ui::views::ViewHolderToken view_holder_token)
|
||||
: view_holder(scenic_session,
|
||||
std::move(view_holder_token),
|
||||
"OverlayViewHolder"),
|
||||
entity_node(scenic_session) {
|
||||
view_holder.SetHitTestBehavior(fuchsia::ui::gfx::HitTestBehavior::kSuppress);
|
||||
entity_node.AddChild(view_holder);
|
||||
}
|
||||
|
||||
void ScenicSurface::OnScenicEvents(
|
||||
std::vector<fuchsia::ui::scenic::Event> events) {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
for (const auto& event : events) {
|
||||
DCHECK(event.is_gfx());
|
||||
switch (event.gfx().Which()) {
|
||||
case fuchsia::ui::gfx::Event::kMetrics: {
|
||||
DCHECK_EQ(event.gfx().metrics().node_id, main_shape_.id());
|
||||
// This is enough to track size because |main_shape_| is 1x1.
|
||||
const auto& metrics = event.gfx().metrics().metrics;
|
||||
main_shape_size_.set_width(metrics.scale_x);
|
||||
main_shape_size_.set_height(metrics.scale_y);
|
||||
|
||||
// Update layout only if Present() was called at least once, i.e. we
|
||||
// have a frame to display.
|
||||
if (last_frame_present_time_ != base::TimeTicks())
|
||||
UpdateViewHolderScene();
|
||||
break;
|
||||
}
|
||||
case fuchsia::ui::gfx::Event::kViewDetachedFromScene: {
|
||||
DCHECK(event.gfx().view_detached_from_scene().view_id == parent_->id());
|
||||
// Present an empty frame to ensure that the outdated content doesn't
|
||||
// become visible if the view is attached again.
|
||||
PresentEmptyImage();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScenicSurface::Present(
|
||||
scoped_refptr<gfx::NativePixmap> primary_plane_pixmap,
|
||||
std::vector<ui::OverlayPlane> overlays_to_present,
|
||||
std::vector<gfx::GpuFenceHandle> acquire_fences,
|
||||
std::vector<gfx::GpuFenceHandle> release_fences,
|
||||
SwapCompletionCallback completion_callback,
|
||||
BufferPresentedCallback presentation_callback) {
|
||||
if (!image_pipe_) {
|
||||
std::move(completion_callback)
|
||||
.Run(gfx::SwapCompletionResult(gfx::SwapResult::SWAP_SKIPPED));
|
||||
return;
|
||||
}
|
||||
|
||||
auto& handle = static_cast<SysmemNativePixmap*>(primary_plane_pixmap.get())
|
||||
->PeekHandle();
|
||||
DCHECK_EQ(handle.buffer_index, 0u);
|
||||
zx_koid_t buffer_collection_id =
|
||||
base::GetKoid(handle.buffer_collection_handle).value();
|
||||
DCHECK(buffer_collection_to_image_id_.contains(buffer_collection_id));
|
||||
uint32_t image_id = buffer_collection_to_image_id_.at(buffer_collection_id);
|
||||
|
||||
TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("viz", "ScenicSurface::PresentFrame",
|
||||
TRACE_ID_LOCAL(this), "image_id", image_id);
|
||||
|
||||
// Always update layout for the first frame.
|
||||
bool layout_update_required = last_frame_present_time_ == base::TimeTicks();
|
||||
|
||||
for (auto& overlay_view : overlay_views_) {
|
||||
overlay_view.second.should_be_visible = false;
|
||||
}
|
||||
|
||||
for (auto& overlay : overlays_to_present) {
|
||||
overlay.pixmap->ScheduleOverlayPlane(window_, overlay.overlay_plane_data,
|
||||
DuplicateGpuFences(acquire_fences),
|
||||
/*release_fences=*/{});
|
||||
|
||||
auto* pixmap = static_cast<SysmemNativePixmap*>(overlay.pixmap.get());
|
||||
auto& overlay_handle = pixmap->PeekHandle();
|
||||
zx_koid_t overlay_id =
|
||||
base::GetKoid(overlay_handle.buffer_collection_handle).value();
|
||||
auto it = overlay_views_.find(overlay_id);
|
||||
|
||||
// If this is a new overlay then attach it.
|
||||
if (it == overlay_views_.end()) {
|
||||
auto token_pair = scenic::ViewTokenPair::New();
|
||||
pixmap->GetScenicOverlayView()->AttachToScenicSurface(
|
||||
std::move(token_pair.view_token));
|
||||
auto emplace_result = overlay_views_.emplace(
|
||||
std::piecewise_construct, std::forward_as_tuple(overlay_id),
|
||||
std::forward_as_tuple(&scenic_session_,
|
||||
std::move(token_pair.view_holder_token)));
|
||||
it = emplace_result.first;
|
||||
layout_update_required = true;
|
||||
}
|
||||
|
||||
auto& overlay_view_info = it->second;
|
||||
overlay_view_info.should_be_visible = true;
|
||||
|
||||
auto& overlay_data = overlay.overlay_plane_data;
|
||||
auto rounded_bounds = gfx::ToRoundedRect(overlay_data.display_bounds);
|
||||
auto transform =
|
||||
absl::get<gfx::OverlayTransform>(overlay_data.plane_transform);
|
||||
if (overlay_view_info.plane_z_order != overlay_data.z_order ||
|
||||
overlay_view_info.display_bounds != rounded_bounds ||
|
||||
overlay_view_info.crop_rect != overlay_data.crop_rect ||
|
||||
overlay_view_info.plane_transform != transform) {
|
||||
overlay_view_info.plane_z_order = overlay_data.z_order;
|
||||
overlay_view_info.display_bounds = rounded_bounds;
|
||||
overlay_view_info.crop_rect = overlay_data.crop_rect;
|
||||
overlay_view_info.plane_transform = transform;
|
||||
layout_update_required = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Hide all overlays views that are not in `overlays_to_present`.
|
||||
auto it = overlay_views_.begin();
|
||||
while (it != overlay_views_.end()) {
|
||||
auto& overlay_view = it->second;
|
||||
if (!overlay_view.should_be_visible) {
|
||||
layout_update_required = true;
|
||||
parent_->DetachChild(overlay_view.entity_node);
|
||||
it = overlay_views_.erase(it);
|
||||
continue;
|
||||
}
|
||||
|
||||
it++;
|
||||
}
|
||||
|
||||
if (layout_update_required) {
|
||||
for (auto& fence : acquire_fences) {
|
||||
scenic_session_.EnqueueAcquireFence(std::move(fence.Clone().owned_event));
|
||||
}
|
||||
UpdateViewHolderScene();
|
||||
}
|
||||
|
||||
pending_frames_.emplace_back(
|
||||
next_frame_ordinal_++, image_id, std::move(primary_plane_pixmap),
|
||||
std::move(completion_callback), std::move(presentation_callback));
|
||||
|
||||
auto now = base::TimeTicks::Now();
|
||||
|
||||
auto present_time = now;
|
||||
|
||||
// If we have PresentationState frame a previously displayed frame then use it
|
||||
// to calculate target timestamp for the new frame.
|
||||
if (presentation_state_) {
|
||||
uint32_t relative_position = pending_frames_.back().ordinal -
|
||||
presentation_state_->presented_frame_ordinal;
|
||||
present_time = presentation_state_->presentation_time +
|
||||
presentation_state_->interval * relative_position -
|
||||
base::Milliseconds(1);
|
||||
present_time = std::max(present_time, now);
|
||||
}
|
||||
|
||||
// Ensure that the target timestamp is not decreasing from the previous frame,
|
||||
// since Scenic doesn't allow it (see crbug.com/1181528).
|
||||
present_time = std::max(present_time, last_frame_present_time_);
|
||||
last_frame_present_time_ = present_time;
|
||||
|
||||
release_fences_from_last_present_.clear();
|
||||
for (auto& fence : release_fences) {
|
||||
release_fences_from_last_present_.push_back(
|
||||
DuplicateZxEvent(fence.owned_event));
|
||||
}
|
||||
|
||||
image_pipe_->PresentImage(
|
||||
image_id, present_time.ToZxTime(),
|
||||
GpuFenceHandlesToZxEvents(std::move(acquire_fences)),
|
||||
GpuFenceHandlesToZxEvents(std::move(release_fences)),
|
||||
fit::bind_member(this, &ScenicSurface::OnPresentComplete));
|
||||
}
|
||||
|
||||
scoped_refptr<gfx::NativePixmap> ScenicSurface::AllocatePrimaryPlanePixmap(
|
||||
VkDevice vk_device,
|
||||
const gfx::Size& size,
|
||||
gfx::BufferFormat buffer_format) {
|
||||
if (!image_pipe_)
|
||||
InitializeImagePipe();
|
||||
|
||||
// Create buffer collection with 2 extra tokens: one for Vulkan and one for
|
||||
// the ImagePipe.
|
||||
fuchsia::sysmem::BufferCollectionTokenSyncPtr collection_token;
|
||||
zx_status_t status =
|
||||
sysmem_buffer_manager_->GetAllocator()->AllocateSharedCollection(
|
||||
collection_token.NewRequest());
|
||||
if (status != ZX_OK) {
|
||||
ZX_DLOG(ERROR, status)
|
||||
<< "fuchsia.sysmem.Allocator.AllocateSharedCollection()";
|
||||
return {};
|
||||
}
|
||||
|
||||
collection_token->SetName(100u, "ChromiumPrimaryPlaneOutput");
|
||||
collection_token->SetDebugClientInfo("vulkan", 0u);
|
||||
|
||||
fuchsia::sysmem::BufferCollectionTokenSyncPtr token_for_scenic;
|
||||
collection_token->Duplicate(ZX_RIGHT_SAME_RIGHTS,
|
||||
token_for_scenic.NewRequest());
|
||||
token_for_scenic->SetDebugClientInfo("scenic", 0u);
|
||||
|
||||
// Register the new buffer collection with the ImagePipe. Since there will
|
||||
// only be a single buffer in the buffer collection we use the same value for
|
||||
// both buffer collection id and image ids.
|
||||
const uint32_t image_id = ++next_unique_id_;
|
||||
image_pipe_->AddBufferCollection(image_id, std::move(token_for_scenic));
|
||||
|
||||
// Register the new buffer collection with sysmem.
|
||||
gfx::NativePixmapHandle pixmap_handle;
|
||||
zx::eventpair service_handle;
|
||||
status = zx::eventpair::create(0, &pixmap_handle.buffer_collection_handle,
|
||||
&service_handle);
|
||||
ZX_DCHECK(status == ZX_OK, status);
|
||||
|
||||
zx_koid_t buffer_collection_id =
|
||||
base::GetKoid(pixmap_handle.buffer_collection_handle).value();
|
||||
buffer_collection_to_image_id_[buffer_collection_id] = image_id;
|
||||
|
||||
auto buffer_collection = sysmem_buffer_manager_->ImportSysmemBufferCollection(
|
||||
vk_device, std::move(service_handle),
|
||||
collection_token.Unbind().TakeChannel(), size, buffer_format,
|
||||
gfx::BufferUsage::SCANOUT, 1,
|
||||
/*register_with_image_pipe=*/false);
|
||||
|
||||
if (!buffer_collection) {
|
||||
ZX_DLOG(ERROR, status) << "Failed to allocate sysmem buffer collection";
|
||||
return {};
|
||||
}
|
||||
|
||||
buffer_collection->AddOnReleasedCallback(
|
||||
base::BindOnce(&ScenicSurface::RemoveBufferCollection,
|
||||
weak_ptr_factory_.GetWeakPtr(), buffer_collection_id));
|
||||
|
||||
fuchsia::sysmem::ImageFormat_2 image_format;
|
||||
image_format.coded_width = size.width();
|
||||
image_format.coded_height = size.height();
|
||||
image_pipe_->AddImage(image_id, image_id, 0, image_format);
|
||||
|
||||
return buffer_collection->CreateNativePixmap(std::move(pixmap_handle), size);
|
||||
}
|
||||
|
||||
void ScenicSurface::SetTextureToNewImagePipe(
|
||||
fidl::InterfaceRequest<fuchsia::images::ImagePipe2> image_pipe_request) {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
uint32_t image_pipe_id = scenic_session_.AllocResourceId();
|
||||
scenic_session_.Enqueue(scenic::NewCreateImagePipe2Cmd(
|
||||
image_pipe_id, std::move(image_pipe_request)));
|
||||
main_material_.SetTexture(image_pipe_id);
|
||||
main_shape_.SetMaterial(main_material_);
|
||||
scenic_session_.ReleaseResource(image_pipe_id);
|
||||
safe_presenter_.QueuePresent();
|
||||
}
|
||||
|
||||
void ScenicSurface::SetTextureToImage(const scenic::Image& image) {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
main_material_.SetTexture(image);
|
||||
main_shape_.SetMaterial(main_material_);
|
||||
}
|
||||
|
||||
mojo::PlatformHandle ScenicSurface::CreateView() {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
|
||||
// Scenic will associate the View and ViewHolder regardless of which it
|
||||
// learns about first, so we don't need to synchronize View creation with
|
||||
// attachment into the scene graph by the caller.
|
||||
auto tokens = scenic::ViewTokenPair::New();
|
||||
parent_ = std::make_unique<scenic::View>(
|
||||
&scenic_session_, std::move(tokens.view_token), "chromium surface");
|
||||
parent_->AddChild(main_shape_);
|
||||
|
||||
// Defer first Present call to SetTextureToNewImagePipe().
|
||||
return mojo::PlatformHandle(std::move(tokens.view_holder_token.value));
|
||||
}
|
||||
|
||||
void ScenicSurface::InitializeImagePipe() {
|
||||
DCHECK(!image_pipe_);
|
||||
|
||||
SetTextureToNewImagePipe(image_pipe_.NewRequest());
|
||||
|
||||
image_pipe_.set_error_handler([this](zx_status_t status) {
|
||||
ZX_LOG(ERROR, status) << "ImagePipe disconnected";
|
||||
|
||||
for (auto& frame : pending_frames_) {
|
||||
std::move(frame.completion_callback)
|
||||
.Run(gfx::SwapCompletionResult(gfx::SwapResult::SWAP_FAILED));
|
||||
}
|
||||
pending_frames_.clear();
|
||||
});
|
||||
}
|
||||
|
||||
void ScenicSurface::RemoveBufferCollection(zx_koid_t buffer_collection_id) {
|
||||
DCHECK(image_pipe_);
|
||||
|
||||
auto iter = buffer_collection_to_image_id_.find(buffer_collection_id);
|
||||
DCHECK(iter != buffer_collection_to_image_id_.end());
|
||||
|
||||
image_pipe_->RemoveBufferCollection(iter->second);
|
||||
buffer_collection_to_image_id_.erase(iter);
|
||||
}
|
||||
|
||||
void ScenicSurface::OnPresentComplete(
|
||||
fuchsia::images::PresentationInfo presentation_info) {
|
||||
TRACE_EVENT_NESTABLE_ASYNC_END1("viz", "ScenicSurface::PresentFrame",
|
||||
TRACE_ID_LOCAL(this), "image_id",
|
||||
pending_frames_.front().image_id);
|
||||
|
||||
auto presentation_time =
|
||||
base::TimeTicks::FromZxTime(presentation_info.presentation_time);
|
||||
auto presentation_interval =
|
||||
base::TimeDelta::FromZxDuration(presentation_info.presentation_interval);
|
||||
|
||||
auto& frame = pending_frames_.front();
|
||||
|
||||
std::move(frame.completion_callback)
|
||||
.Run(gfx::SwapCompletionResult(gfx::SwapResult::SWAP_ACK));
|
||||
std::move(frame.presentation_callback)
|
||||
.Run(gfx::PresentationFeedback(presentation_time, presentation_interval,
|
||||
gfx::PresentationFeedback::kVSync));
|
||||
|
||||
presentation_state_ =
|
||||
PresentationState{static_cast<int>(frame.ordinal), presentation_time,
|
||||
presentation_interval};
|
||||
|
||||
pending_frames_.pop_front();
|
||||
}
|
||||
|
||||
void ScenicSurface::UpdateViewHolderScene() {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
|
||||
// Layout will be updated once we receive view size.
|
||||
if (main_shape_size_.IsEmpty())
|
||||
return;
|
||||
|
||||
// |plane_z_order| for main surface is 0.
|
||||
int min_z_order = 0;
|
||||
for (auto& item : overlay_views_) {
|
||||
auto& overlay_view = item.second;
|
||||
min_z_order = std::min(overlay_view.plane_z_order, min_z_order);
|
||||
}
|
||||
|
||||
for (auto& item : overlay_views_) {
|
||||
auto& overlay_view = item.second;
|
||||
|
||||
// No-op if the node is already attached.
|
||||
parent_->AddChild(overlay_view.entity_node);
|
||||
|
||||
// Apply view bound clipping around the ImagePipe that has size 1x1 and
|
||||
// centered at (0, 0).
|
||||
fuchsia::ui::gfx::ViewProperties view_properties;
|
||||
const float left_bound = -0.5f + overlay_view.crop_rect.x();
|
||||
const float top_bound = -0.5f + overlay_view.crop_rect.y();
|
||||
view_properties.bounding_box = {
|
||||
{left_bound, top_bound, 0.f},
|
||||
{left_bound + overlay_view.crop_rect.width(),
|
||||
top_bound + overlay_view.crop_rect.height(), 0.f}};
|
||||
view_properties.focus_change = false;
|
||||
overlay_view.view_holder.SetViewProperties(std::move(view_properties));
|
||||
|
||||
// We receive |display_bounds| in screen coordinates. Convert them to fit
|
||||
// 1x1 View, which is later scaled up by the browser process.
|
||||
float scaled_width =
|
||||
overlay_view.display_bounds.width() /
|
||||
(overlay_view.crop_rect.width() * main_shape_size_.width());
|
||||
float scaled_height =
|
||||
overlay_view.display_bounds.height() /
|
||||
(overlay_view.crop_rect.height() * main_shape_size_.height());
|
||||
const float scaled_x =
|
||||
overlay_view.display_bounds.x() / main_shape_size_.width();
|
||||
const float scaled_y =
|
||||
overlay_view.display_bounds.y() / main_shape_size_.height();
|
||||
|
||||
// Position ImagePipe based on the display bounds given.
|
||||
overlay_view.entity_node.SetTranslation(
|
||||
-0.5f + scaled_x + scaled_width / 2,
|
||||
-0.5f + scaled_y + scaled_height / 2,
|
||||
(min_z_order - overlay_view.plane_z_order) * kElevationStep);
|
||||
|
||||
// Apply rotation if given. Scenic expects rotation passed as Quaternion.
|
||||
const float angle = OverlayTransformToRadians(overlay_view.plane_transform);
|
||||
overlay_view.entity_node.SetRotation(
|
||||
{0.f, 0.f, sinf(angle * .5f), cosf(angle * .5f)});
|
||||
|
||||
// Scenic applies scaling before rotation.
|
||||
if (overlay_view.plane_transform == gfx::OVERLAY_TRANSFORM_ROTATE_90 ||
|
||||
overlay_view.plane_transform == gfx::OVERLAY_TRANSFORM_ROTATE_270) {
|
||||
std::swap(scaled_width, scaled_height);
|
||||
}
|
||||
|
||||
// Scenic expects flip as negative scaling.
|
||||
if (overlay_view.plane_transform ==
|
||||
gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL) {
|
||||
scaled_width = -scaled_width;
|
||||
} else if (overlay_view.plane_transform ==
|
||||
gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL) {
|
||||
scaled_height = -scaled_height;
|
||||
}
|
||||
|
||||
// Scale ImagePipe based on the display bounds and clip rect given.
|
||||
overlay_view.entity_node.SetScale(scaled_width, scaled_height, 1.f);
|
||||
}
|
||||
|
||||
main_material_.SetColor(255, 255, 255, 0 > min_z_order ? 254 : 255);
|
||||
main_shape_.SetTranslation(0.f, 0.f, min_z_order * kElevationStep);
|
||||
|
||||
safe_presenter_.QueuePresent();
|
||||
}
|
||||
|
||||
void ScenicSurface::PresentEmptyImage() {
|
||||
if (last_frame_present_time_ == base::TimeTicks())
|
||||
return;
|
||||
|
||||
fuchsia::sysmem::BufferCollectionTokenSyncPtr dummy_collection_token;
|
||||
zx_status_t status =
|
||||
sysmem_buffer_manager_->GetAllocator()->AllocateSharedCollection(
|
||||
dummy_collection_token.NewRequest());
|
||||
if (status != ZX_OK) {
|
||||
ZX_DLOG(ERROR, status)
|
||||
<< "fuchsia.sysmem.Allocator.AllocateSharedCollection()";
|
||||
return;
|
||||
}
|
||||
dummy_collection_token->SetName(100u, "DummyImageCollection");
|
||||
dummy_collection_token->SetDebugClientInfo("chromium", 0u);
|
||||
|
||||
fuchsia::sysmem::BufferCollectionTokenSyncPtr token_for_scenic;
|
||||
dummy_collection_token->Duplicate(ZX_RIGHT_SAME_RIGHTS,
|
||||
token_for_scenic.NewRequest());
|
||||
token_for_scenic->SetDebugClientInfo("scenic", 0u);
|
||||
|
||||
const uint32_t image_id = ++next_unique_id_;
|
||||
image_pipe_->AddBufferCollection(image_id, std::move(token_for_scenic));
|
||||
|
||||
// Synchroniously wait for the collection to be allocated before proceeding.
|
||||
fuchsia::sysmem::BufferCollectionSyncPtr dummy_collection;
|
||||
status = sysmem_buffer_manager_->GetAllocator()->BindSharedCollection(
|
||||
std::move(dummy_collection_token), dummy_collection.NewRequest());
|
||||
if (status != ZX_OK) {
|
||||
ZX_DLOG(ERROR, status) << "fuchsia.sysmem.Allocator.BindSharedCollection()";
|
||||
return;
|
||||
}
|
||||
|
||||
fuchsia::sysmem::BufferCollectionConstraints constraints;
|
||||
constraints.usage.none = fuchsia::sysmem::noneUsage;
|
||||
constraints.min_buffer_count = 1;
|
||||
constraints.image_format_constraints_count = 0;
|
||||
status = dummy_collection->SetConstraints(/*has_constraints=*/true,
|
||||
std::move(constraints));
|
||||
zx_status_t wait_status;
|
||||
fuchsia::sysmem::BufferCollectionInfo_2 buffers_info;
|
||||
status =
|
||||
dummy_collection->WaitForBuffersAllocated(&wait_status, &buffers_info);
|
||||
if (status != ZX_OK) {
|
||||
ZX_DLOG(ERROR, status) << "fuchsia.sysmem.BufferCollection failed";
|
||||
return;
|
||||
}
|
||||
dummy_collection->Close();
|
||||
|
||||
// Present the first image from the collection.
|
||||
fuchsia::sysmem::ImageFormat_2 image_format;
|
||||
image_format.coded_width = 1;
|
||||
image_format.coded_height = 1;
|
||||
image_pipe_->AddImage(image_id, image_id, 0, image_format);
|
||||
|
||||
image_pipe_->PresentImage(image_id, last_frame_present_time_.ToZxTime(), {},
|
||||
{}, [](fuchsia::images::PresentationInfo) {});
|
||||
image_pipe_->RemoveBufferCollection(image_id);
|
||||
}
|
||||
|
||||
ScenicSurface::PresentedFrame::PresentedFrame(
|
||||
uint32_t ordinal,
|
||||
uint32_t image_id,
|
||||
scoped_refptr<gfx::NativePixmap> primary_plane,
|
||||
SwapCompletionCallback completion_callback,
|
||||
BufferPresentedCallback presentation_callback)
|
||||
: ordinal(ordinal),
|
||||
image_id(image_id),
|
||||
primary_plane(std::move(primary_plane)),
|
||||
completion_callback(std::move(completion_callback)),
|
||||
presentation_callback(std::move(presentation_callback)) {}
|
||||
ScenicSurface::PresentedFrame::~PresentedFrame() = default;
|
||||
|
||||
ScenicSurface::PresentedFrame::PresentedFrame(PresentedFrame&&) = default;
|
||||
ScenicSurface::PresentedFrame& ScenicSurface::PresentedFrame::operator=(
|
||||
PresentedFrame&&) = default;
|
||||
|
||||
} // namespace ui
|
@ -1,204 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// 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_SURFACE_H_
|
||||
#define UI_OZONE_PLATFORM_SCENIC_SCENIC_SURFACE_H_
|
||||
|
||||
#include <fuchsia/ui/scenic/cpp/fidl.h>
|
||||
#include <lib/ui/scenic/cpp/resources.h>
|
||||
#include <lib/ui/scenic/cpp/session.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "base/containers/circular_deque.h"
|
||||
#include "base/containers/flat_map.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/threading/thread_checker.h"
|
||||
#include "base/time/time.h"
|
||||
#include "mojo/public/cpp/platform/platform_handle.h"
|
||||
#include "ui/gfx/geometry/rect.h"
|
||||
#include "ui/gfx/geometry/rect_f.h"
|
||||
#include "ui/gfx/geometry/size_f.h"
|
||||
#include "ui/gfx/native_pixmap.h"
|
||||
#include "ui/gfx/native_pixmap_handle.h"
|
||||
#include "ui/gfx/native_widget_types.h"
|
||||
#include "ui/gfx/overlay_transform.h"
|
||||
#include "ui/ozone/platform/scenic/safe_presenter.h"
|
||||
#include "ui/ozone/public/platform_window_surface.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
class ScenicSurfaceFactory;
|
||||
class SysmemBufferManager;
|
||||
|
||||
// Holder for Scenic resources backing rendering surface.
|
||||
//
|
||||
// This object creates some simple Scenic resources for containing a window's
|
||||
// texture, and attaches them to the parent View (by sending an IPC to the
|
||||
// browser process).
|
||||
//
|
||||
// The texture is updated through an image pipe.
|
||||
class ScenicSurface : public PlatformWindowSurface {
|
||||
public:
|
||||
ScenicSurface(
|
||||
ScenicSurfaceFactory* scenic_surface_factory,
|
||||
SysmemBufferManager* sysmem_buffer_manager,
|
||||
gfx::AcceleratedWidget window,
|
||||
scenic::SessionPtrAndListenerRequest sesion_and_listener_request);
|
||||
|
||||
ScenicSurface(const ScenicSurface&) = delete;
|
||||
ScenicSurface& operator=(const ScenicSurface&) = delete;
|
||||
|
||||
~ScenicSurface() override;
|
||||
|
||||
// PlatformWindowSurface overrides.
|
||||
void Present(scoped_refptr<gfx::NativePixmap> primary_plane_pixmap,
|
||||
std::vector<ui::OverlayPlane> overlays,
|
||||
std::vector<gfx::GpuFenceHandle> acquire_fences,
|
||||
std::vector<gfx::GpuFenceHandle> release_fences,
|
||||
SwapCompletionCallback completion_callback,
|
||||
BufferPresentedCallback presentation_callback) override;
|
||||
|
||||
// Allocates a new NativePixmap for the primary plane. The first time is
|
||||
// invoked |image_pipe_| will be initialized.
|
||||
scoped_refptr<gfx::NativePixmap> AllocatePrimaryPlanePixmap(
|
||||
VkDevice vk_device,
|
||||
const gfx::Size& size,
|
||||
gfx::BufferFormat buffer_format);
|
||||
|
||||
// Sets the texture of the surface to a new image pipe.
|
||||
void SetTextureToNewImagePipe(
|
||||
fidl::InterfaceRequest<fuchsia::images::ImagePipe2> image_pipe_request);
|
||||
|
||||
// Sets the texture of the surface to an image resource.
|
||||
void SetTextureToImage(const scenic::Image& image);
|
||||
|
||||
// Creates a View for this surface, and returns a ViewHolderToken handle
|
||||
// that can be used to attach it into a scene graph.
|
||||
mojo::PlatformHandle CreateView();
|
||||
|
||||
void OnScenicEvents(std::vector<fuchsia::ui::scenic::Event> events);
|
||||
|
||||
void AssertBelongsToCurrentThread() {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
}
|
||||
|
||||
scenic::Session* scenic_session() {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
return &scenic_session_;
|
||||
}
|
||||
|
||||
SafePresenter* safe_presenter() {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
return &safe_presenter_;
|
||||
}
|
||||
|
||||
private:
|
||||
struct PresentationState {
|
||||
int presented_frame_ordinal;
|
||||
base::TimeTicks presentation_time;
|
||||
base::TimeDelta interval;
|
||||
};
|
||||
|
||||
struct PresentedFrame {
|
||||
PresentedFrame(uint32_t ordinal,
|
||||
uint32_t image_id,
|
||||
scoped_refptr<gfx::NativePixmap> primary_plane,
|
||||
SwapCompletionCallback completion_callback,
|
||||
BufferPresentedCallback presentation_callback);
|
||||
PresentedFrame(PresentedFrame&& other);
|
||||
PresentedFrame& operator=(PresentedFrame&& other);
|
||||
~PresentedFrame();
|
||||
|
||||
uint32_t ordinal;
|
||||
uint32_t image_id;
|
||||
|
||||
// Ensures the pixmap is not destroyed until after frame is presented.
|
||||
scoped_refptr<gfx::NativePixmap> primary_plane;
|
||||
|
||||
SwapCompletionCallback completion_callback;
|
||||
BufferPresentedCallback presentation_callback;
|
||||
};
|
||||
|
||||
void InitializeImagePipe();
|
||||
|
||||
// Removes a buffer collection registered with |image_pipe_| when it's no
|
||||
// longer needed.
|
||||
void RemoveBufferCollection(zx_koid_t buffer_collection_id);
|
||||
void OnPresentComplete(fuchsia::images::PresentationInfo presentation_info);
|
||||
void UpdateViewHolderScene();
|
||||
|
||||
void PresentEmptyImage();
|
||||
|
||||
scenic::Session scenic_session_;
|
||||
std::unique_ptr<scenic::View> parent_;
|
||||
|
||||
// Used for safely queueing Present() operations on |scenic_session_|.
|
||||
SafePresenter safe_presenter_;
|
||||
|
||||
fuchsia::images::ImagePipe2Ptr image_pipe_;
|
||||
|
||||
// Unique ids to be used as both image and uint32_t buffer collection ids.
|
||||
uint32_t next_unique_id_ = 0;
|
||||
|
||||
// Mapping between the SysmemBufferCollectionId stored in NativePixmapHandles
|
||||
// and uint32_t id registered with image pipe.
|
||||
base::flat_map<zx_koid_t, uint32_t> buffer_collection_to_image_id_;
|
||||
|
||||
// Ordinal that will be assigned to the next frame. Ordinals are used to
|
||||
// calculate frame position relative to the current frame stored in
|
||||
// |presentation_state_|. They will wrap around when reaching 2^32, but the
|
||||
// math used to calculate relative position will still work as expected.
|
||||
uint32_t next_frame_ordinal_ = 0;
|
||||
|
||||
// Presentation information received from ImagePipe after rendering a frame.
|
||||
// Used to calculate target presentation time for the frames presented in the
|
||||
// future.
|
||||
absl::optional<PresentationState> presentation_state_;
|
||||
base::TimeTicks last_frame_present_time_;
|
||||
|
||||
base::circular_deque<PresentedFrame> pending_frames_;
|
||||
|
||||
std::vector<zx::event> release_fences_from_last_present_;
|
||||
|
||||
// Scenic resources used for the primary plane, that is not an overlay.
|
||||
scenic::ShapeNode main_shape_;
|
||||
scenic::Material main_material_;
|
||||
gfx::SizeF main_shape_size_;
|
||||
|
||||
ScenicSurfaceFactory* const scenic_surface_factory_;
|
||||
SysmemBufferManager* const sysmem_buffer_manager_;
|
||||
const gfx::AcceleratedWidget window_;
|
||||
|
||||
struct OverlayViewInfo {
|
||||
OverlayViewInfo(scenic::Session* scenic_session,
|
||||
fuchsia::ui::views::ViewHolderToken view_holder_token);
|
||||
|
||||
scenic::ViewHolder view_holder;
|
||||
scenic::EntityNode entity_node;
|
||||
|
||||
int plane_z_order = 0;
|
||||
gfx::Rect display_bounds;
|
||||
gfx::RectF crop_rect;
|
||||
gfx::OverlayTransform plane_transform;
|
||||
|
||||
// Used only in `Present()` in order to update `visible`.
|
||||
bool should_be_visible = false;
|
||||
};
|
||||
|
||||
// Current set of overlays. Identified by koid of the buffer collection
|
||||
// handle.
|
||||
std::unordered_map<zx_koid_t, OverlayViewInfo> overlay_views_;
|
||||
|
||||
THREAD_CHECKER(thread_checker_);
|
||||
|
||||
base::WeakPtrFactory<ScenicSurface> weak_ptr_factory_{this};
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
|
||||
#endif // UI_OZONE_PLATFORM_SCENIC_SCENIC_SURFACE_H_
|
@ -1,294 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// 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_surface_factory.h"
|
||||
|
||||
#include <lib/sys/cpp/component_context.h>
|
||||
#include <lib/zx/event.h>
|
||||
#include <memory>
|
||||
|
||||
#include "base/containers/contains.h"
|
||||
#include "base/fuchsia/fuchsia_logging.h"
|
||||
#include "base/fuchsia/process_context.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/memory/ptr_util.h"
|
||||
#include "base/task/single_thread_task_runner.h"
|
||||
#include "gpu/vulkan/vulkan_device_queue.h"
|
||||
#include "third_party/angle/src/common/fuchsia_egl/fuchsia_egl.h"
|
||||
#include "ui/gfx/geometry/skia_conversions.h"
|
||||
#include "ui/gfx/native_pixmap.h"
|
||||
#include "ui/gfx/vsync_provider.h"
|
||||
#include "ui/gl/gl_surface_egl.h"
|
||||
#include "ui/ozone/common/egl_util.h"
|
||||
#include "ui/ozone/common/gl_ozone_egl.h"
|
||||
#include "ui/ozone/platform/scenic/scenic_gpu_service.h"
|
||||
#include "ui/ozone/platform/scenic/scenic_surface.h"
|
||||
#include "ui/ozone/platform/scenic/scenic_window.h"
|
||||
#include "ui/ozone/platform/scenic/scenic_window_canvas.h"
|
||||
#include "ui/ozone/platform/scenic/scenic_window_manager.h"
|
||||
#include "ui/ozone/platform/scenic/sysmem_buffer_collection.h"
|
||||
#include "ui/ozone/platform/scenic/vulkan_implementation_scenic.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
namespace {
|
||||
|
||||
fuchsia::ui::scenic::ScenicPtr ConnectToScenic() {
|
||||
fuchsia::ui::scenic::ScenicPtr scenic =
|
||||
base::ComponentContextForProcess()
|
||||
->svc()
|
||||
->Connect<fuchsia::ui::scenic::Scenic>();
|
||||
scenic.set_error_handler(
|
||||
base::LogFidlErrorAndExitProcess(FROM_HERE, "fuchsia.ui.scenic.Scenic"));
|
||||
return scenic;
|
||||
}
|
||||
|
||||
class GLOzoneEGLScenic : public GLOzoneEGL {
|
||||
public:
|
||||
GLOzoneEGLScenic() {}
|
||||
|
||||
GLOzoneEGLScenic(const GLOzoneEGLScenic&) = delete;
|
||||
GLOzoneEGLScenic& operator=(const GLOzoneEGLScenic&) = delete;
|
||||
|
||||
~GLOzoneEGLScenic() override = default;
|
||||
|
||||
// GLOzone:
|
||||
scoped_refptr<gl::GLSurface> CreateViewGLSurface(
|
||||
gl::GLDisplay* display,
|
||||
gfx::AcceleratedWidget window) override {
|
||||
// GL rendering to Flatland views is not supported. This function is
|
||||
// used only for unittests. Return an off-screen surface, so the tests pass.
|
||||
// TODO(crbug.com/1271760): Use Vulkan in unittests and remove this hack.
|
||||
return gl::InitializeGLSurface(base::MakeRefCounted<gl::SurfacelessEGL>(
|
||||
display->GetAs<gl::GLDisplayEGL>(), gfx::Size(100, 100)));
|
||||
}
|
||||
|
||||
scoped_refptr<gl::GLSurface> CreateOffscreenGLSurface(
|
||||
gl::GLDisplay* display,
|
||||
const gfx::Size& size) override {
|
||||
return gl::InitializeGLSurface(
|
||||
base::MakeRefCounted<gl::PbufferGLSurfaceEGL>(
|
||||
display->GetAs<gl::GLDisplayEGL>(), size));
|
||||
}
|
||||
|
||||
gl::EGLDisplayPlatform GetNativeDisplay() override {
|
||||
return gl::EGLDisplayPlatform(EGL_DEFAULT_DISPLAY);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool LoadGLES2Bindings(
|
||||
const gl::GLImplementationParts& implementation) override {
|
||||
return LoadDefaultEGLGLES2Bindings(implementation);
|
||||
}
|
||||
};
|
||||
|
||||
fuchsia::sysmem::AllocatorHandle ConnectSysmemAllocator() {
|
||||
fuchsia::sysmem::AllocatorHandle allocator;
|
||||
base::ComponentContextForProcess()->svc()->Connect(allocator.NewRequest());
|
||||
return allocator;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ScenicSurfaceFactory::ScenicSurfaceFactory()
|
||||
: egl_implementation_(std::make_unique<GLOzoneEGLScenic>()),
|
||||
sysmem_buffer_manager_(this),
|
||||
weak_ptr_factory_(this) {}
|
||||
|
||||
ScenicSurfaceFactory::~ScenicSurfaceFactory() {
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
void ScenicSurfaceFactory::Initialize(
|
||||
mojo::PendingRemote<mojom::ScenicGpuHost> gpu_host) {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
base::AutoLock lock(surface_lock_);
|
||||
DCHECK(surface_map_.empty());
|
||||
|
||||
main_thread_task_runner_ = base::SingleThreadTaskRunner::GetCurrentDefault();
|
||||
DCHECK(main_thread_task_runner_);
|
||||
|
||||
DCHECK(!gpu_host_);
|
||||
gpu_host_.Bind(std::move(gpu_host));
|
||||
|
||||
sysmem_buffer_manager_.Initialize(ConnectSysmemAllocator());
|
||||
|
||||
// Scenic is lazily connected to avoid a dependency in headless mode.
|
||||
DCHECK(!scenic_);
|
||||
}
|
||||
|
||||
void ScenicSurfaceFactory::Shutdown() {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
base::AutoLock lock(surface_lock_);
|
||||
DCHECK(surface_map_.empty());
|
||||
main_thread_task_runner_ = nullptr;
|
||||
gpu_host_.reset();
|
||||
sysmem_buffer_manager_.Shutdown();
|
||||
scenic_ = nullptr;
|
||||
}
|
||||
|
||||
std::vector<gl::GLImplementationParts>
|
||||
ScenicSurfaceFactory::GetAllowedGLImplementations() {
|
||||
return std::vector<gl::GLImplementationParts>{
|
||||
gl::GLImplementationParts(gl::kGLImplementationEGLANGLE),
|
||||
gl::GLImplementationParts(gl::kGLImplementationEGLGLES2),
|
||||
gl::GLImplementationParts(gl::kGLImplementationStubGL),
|
||||
};
|
||||
}
|
||||
|
||||
GLOzone* ScenicSurfaceFactory::GetGLOzone(
|
||||
const gl::GLImplementationParts& implementation) {
|
||||
switch (implementation.gl) {
|
||||
case gl::kGLImplementationEGLGLES2:
|
||||
case gl::kGLImplementationEGLANGLE:
|
||||
return egl_implementation_.get();
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<PlatformWindowSurface>
|
||||
ScenicSurfaceFactory::CreatePlatformWindowSurface(
|
||||
gfx::AcceleratedWidget window) {
|
||||
DCHECK_NE(window, gfx::kNullAcceleratedWidget);
|
||||
auto surface = std::make_unique<ScenicSurface>(this, &sysmem_buffer_manager_,
|
||||
window, CreateScenicSession());
|
||||
main_thread_task_runner_->PostTask(
|
||||
FROM_HERE, base::BindOnce(&ScenicSurfaceFactory::AttachSurfaceToWindow,
|
||||
weak_ptr_factory_.GetWeakPtr(), window,
|
||||
surface->CreateView()));
|
||||
return surface;
|
||||
}
|
||||
|
||||
std::unique_ptr<SurfaceOzoneCanvas> ScenicSurfaceFactory::CreateCanvasForWidget(
|
||||
gfx::AcceleratedWidget widget) {
|
||||
ScenicSurface* surface = GetSurface(widget);
|
||||
return std::make_unique<ScenicWindowCanvas>(surface);
|
||||
}
|
||||
|
||||
scoped_refptr<gfx::NativePixmap> ScenicSurfaceFactory::CreateNativePixmap(
|
||||
gfx::AcceleratedWidget widget,
|
||||
gpu::VulkanDeviceQueue* device_queue,
|
||||
gfx::Size size,
|
||||
gfx::BufferFormat format,
|
||||
gfx::BufferUsage usage,
|
||||
absl::optional<gfx::Size> framebuffer_size) {
|
||||
DCHECK(!framebuffer_size || framebuffer_size == size);
|
||||
|
||||
VkDevice vk_device = device_queue->GetVulkanDevice();
|
||||
if (widget != gfx::kNullAcceleratedWidget &&
|
||||
usage == gfx::BufferUsage::SCANOUT) {
|
||||
// The usage SCANOUT is for a primary plane buffer.
|
||||
auto* surface = GetSurface(widget);
|
||||
CHECK(surface);
|
||||
return surface->AllocatePrimaryPlanePixmap(vk_device, size, format);
|
||||
}
|
||||
|
||||
return sysmem_buffer_manager_.CreateNativePixmap(vk_device, size, format,
|
||||
usage);
|
||||
}
|
||||
|
||||
void ScenicSurfaceFactory::CreateNativePixmapAsync(
|
||||
gfx::AcceleratedWidget widget,
|
||||
gpu::VulkanDeviceQueue* device_queue,
|
||||
gfx::Size size,
|
||||
gfx::BufferFormat format,
|
||||
gfx::BufferUsage usage,
|
||||
NativePixmapCallback callback) {
|
||||
std::move(callback).Run(
|
||||
CreateNativePixmap(widget, device_queue, size, format, usage));
|
||||
}
|
||||
|
||||
scoped_refptr<gfx::NativePixmap>
|
||||
ScenicSurfaceFactory::CreateNativePixmapFromHandle(
|
||||
gfx::AcceleratedWidget widget,
|
||||
gfx::Size size,
|
||||
gfx::BufferFormat format,
|
||||
gfx::NativePixmapHandle handle) {
|
||||
auto collection = sysmem_buffer_manager_.GetCollectionByHandle(
|
||||
handle.buffer_collection_handle);
|
||||
if (!collection)
|
||||
return nullptr;
|
||||
|
||||
return collection->CreateNativePixmap(std::move(handle), size);
|
||||
}
|
||||
|
||||
std::unique_ptr<gpu::VulkanImplementation>
|
||||
ScenicSurfaceFactory::CreateVulkanImplementation(bool use_swiftshader,
|
||||
bool allow_protected_memory) {
|
||||
return std::make_unique<ui::VulkanImplementationScenic>(
|
||||
this, &sysmem_buffer_manager_, use_swiftshader, allow_protected_memory);
|
||||
}
|
||||
|
||||
std::vector<gfx::BufferFormat>
|
||||
ScenicSurfaceFactory::GetSupportedFormatsForTexturing() const {
|
||||
return {
|
||||
gfx::BufferFormat::R_8,
|
||||
gfx::BufferFormat::RG_88,
|
||||
gfx::BufferFormat::RGBA_8888,
|
||||
gfx::BufferFormat::RGBX_8888,
|
||||
gfx::BufferFormat::BGRA_8888,
|
||||
gfx::BufferFormat::BGRX_8888,
|
||||
gfx::BufferFormat::YUV_420_BIPLANAR,
|
||||
};
|
||||
}
|
||||
|
||||
void ScenicSurfaceFactory::AddSurface(gfx::AcceleratedWidget widget,
|
||||
ScenicSurface* surface) {
|
||||
base::AutoLock lock(surface_lock_);
|
||||
DCHECK(!base::Contains(surface_map_, widget));
|
||||
surface->AssertBelongsToCurrentThread();
|
||||
surface_map_.emplace(widget, surface);
|
||||
}
|
||||
|
||||
void ScenicSurfaceFactory::RemoveSurface(gfx::AcceleratedWidget widget) {
|
||||
base::AutoLock lock(surface_lock_);
|
||||
auto it = surface_map_.find(widget);
|
||||
DCHECK(it != surface_map_.end());
|
||||
ScenicSurface* surface = it->second;
|
||||
surface->AssertBelongsToCurrentThread();
|
||||
surface_map_.erase(it);
|
||||
}
|
||||
|
||||
ScenicSurface* ScenicSurfaceFactory::GetSurface(gfx::AcceleratedWidget widget) {
|
||||
base::AutoLock lock(surface_lock_);
|
||||
auto it = surface_map_.find(widget);
|
||||
if (it == surface_map_.end())
|
||||
return nullptr;
|
||||
|
||||
ScenicSurface* surface = it->second;
|
||||
surface->AssertBelongsToCurrentThread();
|
||||
return surface;
|
||||
}
|
||||
|
||||
scenic::SessionPtrAndListenerRequest
|
||||
ScenicSurfaceFactory::CreateScenicSession() {
|
||||
fuchsia::ui::scenic::SessionPtr session;
|
||||
fidl::InterfaceHandle<fuchsia::ui::scenic::SessionListener> listener_handle;
|
||||
auto listener_request = listener_handle.NewRequest();
|
||||
|
||||
{
|
||||
// Cache Scenic connection for main thread. For other treads create
|
||||
// one-shot connection.
|
||||
fuchsia::ui::scenic::ScenicPtr local_scenic;
|
||||
fuchsia::ui::scenic::ScenicPtr* scenic =
|
||||
main_thread_task_runner_->BelongsToCurrentThread() ? &scenic_
|
||||
: &local_scenic;
|
||||
if (!*scenic)
|
||||
*scenic = ConnectToScenic();
|
||||
(*scenic)->CreateSession(session.NewRequest(), std::move(listener_handle));
|
||||
}
|
||||
|
||||
return {std::move(session), std::move(listener_request)};
|
||||
}
|
||||
|
||||
void ScenicSurfaceFactory::AttachSurfaceToWindow(
|
||||
gfx::AcceleratedWidget window,
|
||||
mojo::PlatformHandle surface_view_holder_token_mojo) {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
gpu_host_->AttachSurfaceToWindow(window,
|
||||
std::move(surface_view_holder_token_mojo));
|
||||
}
|
||||
|
||||
} // namespace ui
|
@ -1,125 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// 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_SURFACE_FACTORY_H_
|
||||
#define UI_OZONE_PLATFORM_SCENIC_SCENIC_SURFACE_FACTORY_H_
|
||||
|
||||
#include <fuchsia/ui/scenic/cpp/fidl.h>
|
||||
#include <lib/ui/scenic/cpp/session.h>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "base/containers/flat_map.h"
|
||||
#include "base/task/single_thread_task_runner.h"
|
||||
#include "base/thread_annotations.h"
|
||||
#include "base/threading/thread_checker.h"
|
||||
#include "mojo/public/cpp/bindings/pending_remote.h"
|
||||
#include "mojo/public/cpp/bindings/remote.h"
|
||||
#include "mojo/public/cpp/system/handle.h"
|
||||
#include "ui/ozone/platform/scenic/mojom/scenic_gpu_host.mojom.h"
|
||||
#include "ui/ozone/platform/scenic/sysmem_buffer_manager.h"
|
||||
#include "ui/ozone/public/gl_ozone.h"
|
||||
#include "ui/ozone/public/surface_factory_ozone.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
class ScenicSurface;
|
||||
|
||||
class ScenicSurfaceFactory : public SurfaceFactoryOzone {
|
||||
public:
|
||||
ScenicSurfaceFactory();
|
||||
|
||||
ScenicSurfaceFactory(const ScenicSurfaceFactory&) = delete;
|
||||
ScenicSurfaceFactory& operator=(const ScenicSurfaceFactory&) = delete;
|
||||
|
||||
~ScenicSurfaceFactory() override;
|
||||
|
||||
// Initializes the surface factory. Binds the surface factory to the
|
||||
// current thread (and thus must run with a message loop).
|
||||
void Initialize(mojo::PendingRemote<mojom::ScenicGpuHost> gpu_host);
|
||||
|
||||
// Disconnects from ScenicGpuHost and detaches from the current thread.
|
||||
// After shutting down, it is safe to call Initialize() again.
|
||||
void Shutdown();
|
||||
|
||||
// SurfaceFactoryOzone implementation.
|
||||
std::vector<gl::GLImplementationParts> GetAllowedGLImplementations() override;
|
||||
GLOzone* GetGLOzone(const gl::GLImplementationParts& implementation) override;
|
||||
std::unique_ptr<PlatformWindowSurface> CreatePlatformWindowSurface(
|
||||
gfx::AcceleratedWidget widget) override;
|
||||
std::unique_ptr<SurfaceOzoneCanvas> CreateCanvasForWidget(
|
||||
gfx::AcceleratedWidget widget) override;
|
||||
scoped_refptr<gfx::NativePixmap> CreateNativePixmap(
|
||||
gfx::AcceleratedWidget widget,
|
||||
gpu::VulkanDeviceQueue* device_queue,
|
||||
gfx::Size size,
|
||||
gfx::BufferFormat format,
|
||||
gfx::BufferUsage usage,
|
||||
absl::optional<gfx::Size> framebuffer_size = absl::nullopt) override;
|
||||
void CreateNativePixmapAsync(gfx::AcceleratedWidget widget,
|
||||
gpu::VulkanDeviceQueue* device_queue,
|
||||
gfx::Size size,
|
||||
gfx::BufferFormat format,
|
||||
gfx::BufferUsage usage,
|
||||
NativePixmapCallback callback) override;
|
||||
scoped_refptr<gfx::NativePixmap> CreateNativePixmapFromHandle(
|
||||
gfx::AcceleratedWidget widget,
|
||||
gfx::Size size,
|
||||
gfx::BufferFormat format,
|
||||
gfx::NativePixmapHandle handle) override;
|
||||
std::unique_ptr<gpu::VulkanImplementation> CreateVulkanImplementation(
|
||||
bool use_swiftshader,
|
||||
bool allow_protected_memory) override;
|
||||
std::vector<gfx::BufferFormat> GetSupportedFormatsForTexturing()
|
||||
const override;
|
||||
|
||||
// Registers a surface for a |widget|.
|
||||
//
|
||||
// Must be called on the thread that owns the surface.
|
||||
void AddSurface(gfx::AcceleratedWidget widget, ScenicSurface* surface)
|
||||
LOCKS_EXCLUDED(surface_lock_);
|
||||
|
||||
// Removes a surface for a |widget|.
|
||||
//
|
||||
// Must be called on the thread that owns the surface.
|
||||
void RemoveSurface(gfx::AcceleratedWidget widget)
|
||||
LOCKS_EXCLUDED(surface_lock_);
|
||||
|
||||
// Returns the surface for a |widget|.
|
||||
//
|
||||
// Must be called on the thread that owns the surface.
|
||||
ScenicSurface* GetSurface(gfx::AcceleratedWidget widget)
|
||||
LOCKS_EXCLUDED(surface_lock_);
|
||||
|
||||
// Creates a new scenic session on any thread.
|
||||
scenic::SessionPtrAndListenerRequest CreateScenicSession();
|
||||
|
||||
private:
|
||||
// Links a surface to its parent window in the host process.
|
||||
void AttachSurfaceToWindow(
|
||||
gfx::AcceleratedWidget window,
|
||||
mojo::PlatformHandle surface_view_holder_token_mojo);
|
||||
|
||||
base::flat_map<gfx::AcceleratedWidget, ScenicSurface*> surface_map_
|
||||
GUARDED_BY(surface_lock_);
|
||||
base::Lock surface_lock_;
|
||||
|
||||
mojo::Remote<mojom::ScenicGpuHost> gpu_host_;
|
||||
std::unique_ptr<GLOzone> egl_implementation_;
|
||||
|
||||
fuchsia::ui::scenic::ScenicPtr scenic_;
|
||||
|
||||
// Task runner for thread that |scenic_| and |gpu_host_| are bound on.
|
||||
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
|
||||
|
||||
SysmemBufferManager sysmem_buffer_manager_;
|
||||
|
||||
THREAD_CHECKER(thread_checker_);
|
||||
|
||||
base::WeakPtrFactory<ScenicSurfaceFactory> weak_ptr_factory_;
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
|
||||
#endif // UI_OZONE_PLATFORM_SCENIC_SCENIC_SURFACE_FACTORY_H_
|
@ -1,495 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// 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_window.h"
|
||||
|
||||
#include <fidl/fuchsia.ui.pointer/cpp/hlcpp_conversion.h>
|
||||
#include <fidl/fuchsia.ui.views/cpp/hlcpp_conversion.h>
|
||||
#include <lib/async/default.h>
|
||||
#include <lib/sys/cpp/component_context.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "base/fuchsia/fuchsia_component_connect.h"
|
||||
#include "base/fuchsia/fuchsia_logging.h"
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "ui/base/cursor/platform_cursor.h"
|
||||
#include "ui/display/types/display_constants.h"
|
||||
#include "ui/events/event.h"
|
||||
#include "ui/events/event_constants.h"
|
||||
#include "ui/events/keycodes/keyboard_code_conversion.h"
|
||||
#include "ui/events/ozone/events_ozone.h"
|
||||
#include "ui/events/platform/platform_event_source.h"
|
||||
#include "ui/ozone/platform/scenic/scenic_window_manager.h"
|
||||
#include "ui/platform_window/fuchsia/scenic_window_delegate.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
namespace {
|
||||
|
||||
// Converts Scenic's rect-based representation of insets to gfx::Insets.
|
||||
// Returns zero-width insets if |inset_from_min| and |inset_from_max| are
|
||||
// uninitialized (indicating that no insets were provided from Scenic).
|
||||
gfx::Insets ConvertInsets(
|
||||
float device_pixel_ratio,
|
||||
const fuchsia::ui::gfx::ViewProperties& view_properties) {
|
||||
return gfx::Insets::TLBR(
|
||||
device_pixel_ratio * view_properties.inset_from_min.y,
|
||||
device_pixel_ratio * view_properties.inset_from_min.x,
|
||||
device_pixel_ratio * view_properties.inset_from_max.y,
|
||||
device_pixel_ratio * view_properties.inset_from_max.x);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ScenicWindow::ScenicWindow(ScenicWindowManager* window_manager,
|
||||
PlatformWindowDelegate* delegate,
|
||||
PlatformWindowInitProperties properties)
|
||||
: manager_(window_manager),
|
||||
delegate_(delegate),
|
||||
scenic_window_delegate_(properties.scenic_window_delegate),
|
||||
window_id_(manager_->AddWindow(this)),
|
||||
view_ref_(std::move(properties.view_ref_pair.view_ref)),
|
||||
view_controller_(std::move(properties.view_controller)),
|
||||
bounds_(delegate_->ConvertRectToPixels(properties.bounds)) {
|
||||
{
|
||||
// Send graphics and input endpoints to Scenic. The endpoints are dormant
|
||||
// until the Session's Present call, at the bottom of this block.
|
||||
fuchsia::ui::scenic::SessionEndpoints endpoints;
|
||||
fuchsia::ui::scenic::SessionPtr session_ptr;
|
||||
endpoints.set_session(session_ptr.NewRequest());
|
||||
fuchsia::ui::scenic::SessionListenerHandle listener_handle;
|
||||
auto listener_request = listener_handle.NewRequest();
|
||||
endpoints.set_session_listener(std::move(listener_handle));
|
||||
|
||||
auto touch_source_endpoints =
|
||||
fidl::CreateEndpoints<fuchsia_ui_pointer::TouchSource>();
|
||||
ZX_CHECK(touch_source_endpoints.is_ok(),
|
||||
touch_source_endpoints.status_value());
|
||||
endpoints.set_touch_source(
|
||||
fidl::NaturalToHLCPP(std::move(touch_source_endpoints->server)));
|
||||
|
||||
auto mouse_source_endpoints =
|
||||
fidl::CreateEndpoints<fuchsia_ui_pointer::MouseSource>();
|
||||
ZX_CHECK(mouse_source_endpoints.is_ok(),
|
||||
mouse_source_endpoints.status_value());
|
||||
endpoints.set_mouse_source(
|
||||
fidl::NaturalToHLCPP(std::move(mouse_source_endpoints->server)));
|
||||
|
||||
endpoints.set_view_ref_focused(view_ref_focused_.NewRequest());
|
||||
manager_->GetScenic()->CreateSessionT(std::move(endpoints), [] {});
|
||||
|
||||
// Set up pointer and focus event processors.
|
||||
pointer_handler_.emplace(std::move(touch_source_endpoints->client),
|
||||
std::move(mouse_source_endpoints->client));
|
||||
pointer_handler_->StartWatching(base::BindRepeating(
|
||||
&ScenicWindow::DispatchEvent,
|
||||
// This is safe since |pointer_handler_| is a class member.
|
||||
base::Unretained(this)));
|
||||
|
||||
view_ref_focused_->Watch(
|
||||
fit::bind_member(this, &ScenicWindow::OnViewRefFocusedWatchResult));
|
||||
view_ref_focused_.set_error_handler([](zx_status_t status) {
|
||||
ZX_LOG(ERROR, status) << "Focus listener disconnected.";
|
||||
});
|
||||
|
||||
// Set up GFX Session and scene resources.
|
||||
scenic_session_.emplace(std::move(session_ptr),
|
||||
std::move(listener_request));
|
||||
scenic_session_->set_error_handler(
|
||||
fit::bind_member(this, &ScenicWindow::OnScenicError));
|
||||
scenic_session_->set_event_handler(
|
||||
fit::bind_member(this, &ScenicWindow::OnScenicEvents));
|
||||
scenic_session_->SetDebugName("Chromium ScenicWindow");
|
||||
|
||||
view_.emplace(&scenic_session_.value(), std::move(properties.view_token),
|
||||
std::move(properties.view_ref_pair.control_ref),
|
||||
CloneViewRef(), "chromium window");
|
||||
|
||||
node_.emplace(&scenic_session_.value());
|
||||
|
||||
// Subscribe to metrics events from the node. Metrics events provide the
|
||||
// device pixel ratio for the screen.
|
||||
node_->SetEventMask(fuchsia::ui::gfx::kMetricsEventMask);
|
||||
|
||||
// To receive metrics events on this node, attach it to the scene graph.
|
||||
view_->AddChild(*node_);
|
||||
|
||||
input_node_.emplace(&scenic_session_.value());
|
||||
render_node_.emplace(&scenic_session_.value());
|
||||
|
||||
safe_presenter_.emplace(&scenic_session_.value());
|
||||
safe_presenter_->QueuePresent();
|
||||
}
|
||||
|
||||
if (view_controller_) {
|
||||
view_controller_.set_error_handler(
|
||||
fit::bind_member(this, &ScenicWindow::OnViewControllerDisconnected));
|
||||
}
|
||||
|
||||
delegate_->OnAcceleratedWidgetAvailable(window_id_);
|
||||
|
||||
if (properties.enable_keyboard) {
|
||||
is_virtual_keyboard_enabled_ = properties.enable_virtual_keyboard;
|
||||
auto keyboard_client_end =
|
||||
base::fuchsia_component::Connect<fuchsia_ui_input3::Keyboard>();
|
||||
CHECK(keyboard_client_end.is_ok())
|
||||
<< base::FidlConnectionErrorMessage(keyboard_client_end);
|
||||
keyboard_fidl_client_.Bind(std::move(keyboard_client_end.value()),
|
||||
async_get_default_dispatcher(),
|
||||
&fidl_error_event_logger_);
|
||||
keyboard_client_ = std::make_unique<KeyboardClient>(
|
||||
keyboard_fidl_client_, fidl::HLCPPToNatural(CloneViewRef()), this);
|
||||
} else {
|
||||
DCHECK(!properties.enable_virtual_keyboard);
|
||||
}
|
||||
}
|
||||
|
||||
ScenicWindow::~ScenicWindow() {
|
||||
manager_->RemoveWindow(window_id_, this);
|
||||
}
|
||||
|
||||
fuchsia::ui::views::ViewRef ScenicWindow::CloneViewRef() {
|
||||
fuchsia::ui::views::ViewRef dup;
|
||||
zx_status_t status =
|
||||
view_ref_.reference.duplicate(ZX_RIGHT_SAME_RIGHTS, &dup.reference);
|
||||
ZX_CHECK(status == ZX_OK, status) << "zx_object_duplicate";
|
||||
return dup;
|
||||
}
|
||||
|
||||
gfx::Rect ScenicWindow::GetBoundsInPixels() const {
|
||||
return bounds_;
|
||||
}
|
||||
|
||||
void ScenicWindow::SetBoundsInPixels(const gfx::Rect& bounds) {
|
||||
// This path should only be reached in tests.
|
||||
bounds_ = bounds;
|
||||
}
|
||||
|
||||
gfx::Rect ScenicWindow::GetBoundsInDIP() const {
|
||||
return delegate_->ConvertRectToDIP(bounds_);
|
||||
}
|
||||
|
||||
void ScenicWindow::SetBoundsInDIP(const gfx::Rect& bounds) {
|
||||
// This path should only be reached in tests.
|
||||
bounds_ = delegate_->ConvertRectToPixels(bounds);
|
||||
}
|
||||
|
||||
void ScenicWindow::SetTitle(const std::u16string& title) {
|
||||
NOTIMPLEMENTED_LOG_ONCE();
|
||||
}
|
||||
|
||||
void ScenicWindow::Show(bool inactive) {
|
||||
if (is_visible_)
|
||||
return;
|
||||
|
||||
is_visible_ = true;
|
||||
|
||||
UpdateRootNodeVisibility();
|
||||
|
||||
// Call Present2() to ensure that the scenic session commands are processed,
|
||||
// which is necessary to receive metrics event from Scenic.
|
||||
safe_presenter_->QueuePresent();
|
||||
}
|
||||
|
||||
void ScenicWindow::Hide() {
|
||||
if (!is_visible_)
|
||||
return;
|
||||
|
||||
is_visible_ = false;
|
||||
|
||||
UpdateRootNodeVisibility();
|
||||
}
|
||||
|
||||
void ScenicWindow::Close() {
|
||||
if (view_controller_) {
|
||||
view_controller_->Dismiss();
|
||||
view_controller_ = nullptr;
|
||||
}
|
||||
Hide();
|
||||
delegate_->OnClosed();
|
||||
}
|
||||
|
||||
bool ScenicWindow::IsVisible() const {
|
||||
return is_visible_;
|
||||
}
|
||||
|
||||
void ScenicWindow::PrepareForShutdown() {
|
||||
NOTIMPLEMENTED_LOG_ONCE();
|
||||
}
|
||||
|
||||
void ScenicWindow::SetCapture() {
|
||||
// TODO(crbug.com/1231516): Use Scenic capture APIs.
|
||||
NOTIMPLEMENTED_LOG_ONCE();
|
||||
has_capture_ = true;
|
||||
}
|
||||
|
||||
void ScenicWindow::ReleaseCapture() {
|
||||
// TODO(crbug.com/1231516): Use Scenic capture APIs.
|
||||
NOTIMPLEMENTED_LOG_ONCE();
|
||||
has_capture_ = false;
|
||||
}
|
||||
|
||||
bool ScenicWindow::HasCapture() const {
|
||||
// TODO(crbug.com/1231516): Use Scenic capture APIs.
|
||||
NOTIMPLEMENTED_LOG_ONCE();
|
||||
return has_capture_;
|
||||
}
|
||||
|
||||
void ScenicWindow::SetFullscreen(bool fullscreen, int64_t target_display_id) {
|
||||
NOTIMPLEMENTED_LOG_ONCE();
|
||||
DCHECK_EQ(target_display_id, display::kInvalidDisplayId);
|
||||
is_fullscreen_ = fullscreen;
|
||||
}
|
||||
|
||||
void ScenicWindow::Maximize() {
|
||||
NOTIMPLEMENTED_LOG_ONCE();
|
||||
}
|
||||
|
||||
void ScenicWindow::Minimize() {
|
||||
NOTIMPLEMENTED_LOG_ONCE();
|
||||
}
|
||||
|
||||
void ScenicWindow::Restore() {
|
||||
NOTIMPLEMENTED_LOG_ONCE();
|
||||
}
|
||||
|
||||
PlatformWindowState ScenicWindow::GetPlatformWindowState() const {
|
||||
if (is_fullscreen_)
|
||||
return PlatformWindowState::kFullScreen;
|
||||
if (!is_view_attached_)
|
||||
return PlatformWindowState::kMinimized;
|
||||
|
||||
// TODO(crbug.com/1241868): We cannot tell what portion of the screen is
|
||||
// occupied by the View, so report is as maximized to reduce the space used
|
||||
// by any browser chrome.
|
||||
return PlatformWindowState::kMaximized;
|
||||
}
|
||||
|
||||
void ScenicWindow::Activate() {
|
||||
NOTIMPLEMENTED_LOG_ONCE();
|
||||
}
|
||||
|
||||
void ScenicWindow::Deactivate() {
|
||||
NOTIMPLEMENTED_LOG_ONCE();
|
||||
}
|
||||
|
||||
void ScenicWindow::SetUseNativeFrame(bool use_native_frame) {}
|
||||
|
||||
bool ScenicWindow::ShouldUseNativeFrame() const {
|
||||
NOTIMPLEMENTED_LOG_ONCE();
|
||||
return false;
|
||||
}
|
||||
|
||||
void ScenicWindow::SetCursor(scoped_refptr<PlatformCursor> cursor) {
|
||||
NOTIMPLEMENTED_LOG_ONCE();
|
||||
}
|
||||
|
||||
void ScenicWindow::MoveCursorTo(const gfx::Point& location) {
|
||||
NOTIMPLEMENTED_LOG_ONCE();
|
||||
}
|
||||
|
||||
void ScenicWindow::ConfineCursorToBounds(const gfx::Rect& bounds) {
|
||||
NOTIMPLEMENTED_LOG_ONCE();
|
||||
}
|
||||
|
||||
void ScenicWindow::SetRestoredBoundsInDIP(const gfx::Rect& bounds) {
|
||||
NOTIMPLEMENTED_LOG_ONCE();
|
||||
}
|
||||
|
||||
gfx::Rect ScenicWindow::GetRestoredBoundsInDIP() const {
|
||||
NOTIMPLEMENTED_LOG_ONCE();
|
||||
return gfx::Rect();
|
||||
}
|
||||
|
||||
void ScenicWindow::SetWindowIcons(const gfx::ImageSkia& window_icon,
|
||||
const gfx::ImageSkia& app_icon) {
|
||||
NOTIMPLEMENTED_LOG_ONCE();
|
||||
}
|
||||
|
||||
void ScenicWindow::SizeConstraintsChanged() {
|
||||
NOTIMPLEMENTED_LOG_ONCE();
|
||||
}
|
||||
|
||||
void ScenicWindow::AttachSurfaceView(
|
||||
fuchsia::ui::views::ViewHolderToken token) {
|
||||
surface_view_holder_ = std::make_unique<scenic::ViewHolder>(
|
||||
&scenic_session_.value(), std::move(token), "chromium window surface");
|
||||
|
||||
// Configure the ViewHolder not to be focusable, or hit-testable, to ensure
|
||||
// that it cannot receive input.
|
||||
fuchsia::ui::gfx::ViewProperties view_properties;
|
||||
view_properties.bounding_box = {{-0.5f, -0.5f, -0.5f}, {0.5f, 0.5f, 0.5f}};
|
||||
view_properties.focus_change = false;
|
||||
surface_view_holder_->SetViewProperties(std::move(view_properties));
|
||||
surface_view_holder_->SetHitTestBehavior(
|
||||
fuchsia::ui::gfx::HitTestBehavior::kSuppress);
|
||||
|
||||
render_node_->DetachChildren();
|
||||
render_node_->AddChild(*surface_view_holder_);
|
||||
|
||||
safe_presenter_->QueuePresent();
|
||||
}
|
||||
|
||||
void ScenicWindow::DispatchEvent(ui::Event* event) {
|
||||
if (event->IsLocatedEvent()) {
|
||||
ui::LocatedEvent* located_event = event->AsLocatedEvent();
|
||||
gfx::PointF location = located_event->location_f();
|
||||
location.Scale(device_pixel_ratio_);
|
||||
located_event->set_location_f(location);
|
||||
}
|
||||
delegate_->DispatchEvent(event);
|
||||
}
|
||||
|
||||
void ScenicWindow::OnScenicError(zx_status_t status) {
|
||||
LOG(ERROR) << "scenic::Session failed with code " << status << ".";
|
||||
delegate_->OnCloseRequest();
|
||||
}
|
||||
|
||||
void ScenicWindow::OnScenicEvents(
|
||||
std::vector<fuchsia::ui::scenic::Event> events) {
|
||||
for (const auto& event : events) {
|
||||
if (event.is_gfx()) {
|
||||
switch (event.gfx().Which()) {
|
||||
case fuchsia::ui::gfx::Event::kMetrics: {
|
||||
if (event.gfx().metrics().node_id != node_->id())
|
||||
continue;
|
||||
OnViewMetrics(event.gfx().metrics().metrics);
|
||||
break;
|
||||
}
|
||||
case fuchsia::ui::gfx::Event::kViewPropertiesChanged: {
|
||||
DCHECK(event.gfx().view_properties_changed().view_id == view_->id());
|
||||
OnViewProperties(event.gfx().view_properties_changed().properties);
|
||||
break;
|
||||
}
|
||||
case fuchsia::ui::gfx::Event::kViewAttachedToScene: {
|
||||
DCHECK(event.gfx().view_attached_to_scene().view_id == view_->id());
|
||||
OnViewAttachedChanged(true);
|
||||
break;
|
||||
}
|
||||
case fuchsia::ui::gfx::Event::kViewDetachedFromScene: {
|
||||
DCHECK(event.gfx().view_detached_from_scene().view_id == view_->id());
|
||||
OnViewAttachedChanged(false);
|
||||
|
||||
// Detach the surface view. This is necessary to ensure that the
|
||||
// current content doesn't become visible when the view is attached
|
||||
// again.
|
||||
render_node_->DetachChildren();
|
||||
surface_view_holder_.reset();
|
||||
safe_presenter_->QueuePresent();
|
||||
|
||||
// Destroy and recreate AcceleratedWidget. This will force the
|
||||
// compositor drop the current LayerTreeFrameSink together with the
|
||||
// corresponding ScenicSurface. They will be created again only after
|
||||
// the window becomes visible again.
|
||||
delegate_->OnAcceleratedWidgetDestroyed();
|
||||
delegate_->OnAcceleratedWidgetAvailable(window_id_);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScenicWindow::OnViewAttachedChanged(bool is_view_attached) {
|
||||
PlatformWindowState old_state = GetPlatformWindowState();
|
||||
is_view_attached_ = is_view_attached;
|
||||
PlatformWindowState new_state = GetPlatformWindowState();
|
||||
if (old_state != new_state) {
|
||||
delegate_->OnWindowStateChanged(old_state, new_state);
|
||||
}
|
||||
}
|
||||
|
||||
void ScenicWindow::OnViewMetrics(const fuchsia::ui::gfx::Metrics& metrics) {
|
||||
device_pixel_ratio_ = std::max(metrics.scale_x, metrics.scale_y);
|
||||
if (scenic_window_delegate_)
|
||||
scenic_window_delegate_->OnScenicPixelScale(this, device_pixel_ratio_);
|
||||
|
||||
if (view_properties_)
|
||||
UpdateSize();
|
||||
}
|
||||
|
||||
void ScenicWindow::OnViewProperties(
|
||||
const fuchsia::ui::gfx::ViewProperties& properties) {
|
||||
view_properties_ = properties;
|
||||
if (device_pixel_ratio_ > 0.0)
|
||||
UpdateSize();
|
||||
}
|
||||
|
||||
void ScenicWindow::OnViewRefFocusedWatchResult(
|
||||
fuchsia::ui::views::FocusState focus_state) {
|
||||
delegate_->OnActivationChanged(focus_state.focused());
|
||||
|
||||
view_ref_focused_->Watch(
|
||||
fit::bind_member(this, &ScenicWindow::OnViewRefFocusedWatchResult));
|
||||
}
|
||||
|
||||
void ScenicWindow::UpdateSize() {
|
||||
DCHECK_GT(device_pixel_ratio_, 0.0);
|
||||
DCHECK(view_properties_);
|
||||
|
||||
const float width = view_properties_->bounding_box.max.x -
|
||||
view_properties_->bounding_box.min.x;
|
||||
const float height = view_properties_->bounding_box.max.y -
|
||||
view_properties_->bounding_box.min.y;
|
||||
|
||||
const gfx::Point old_origin = bounds_.origin();
|
||||
bounds_ = gfx::Rect(ceilf(width * device_pixel_ratio_),
|
||||
ceilf(height * device_pixel_ratio_));
|
||||
|
||||
// Update the root node to be shown, or hidden, based on the View state.
|
||||
// If the root node is not visible then skip resizing content, etc.
|
||||
if (!UpdateRootNodeVisibility())
|
||||
return;
|
||||
|
||||
// Translate the node by half of the view dimensions to put it in the center
|
||||
// of the view.
|
||||
node_->SetTranslation(width / 2.0, height / 2.0, 0.f);
|
||||
|
||||
// Scale the render node so that surface rect can always be 1x1.
|
||||
render_node_->SetScale(width, height, 1.f);
|
||||
|
||||
// Resize input node to cover the whole surface.
|
||||
scenic::Rectangle window_rect(&scenic_session_.value(), width, height);
|
||||
input_node_->SetShape(window_rect);
|
||||
|
||||
// This is necessary when using vulkan because ImagePipes are presented
|
||||
// separately and we need to make sure our sizes change is committed.
|
||||
safe_presenter_->QueuePresent();
|
||||
|
||||
PlatformWindowDelegate::BoundsChange bounds(old_origin != bounds_.origin());
|
||||
bounds.system_ui_overlap =
|
||||
ConvertInsets(device_pixel_ratio_, *view_properties_);
|
||||
delegate_->OnBoundsChanged(bounds);
|
||||
}
|
||||
|
||||
bool ScenicWindow::UpdateRootNodeVisibility() {
|
||||
bool should_show_root_node = is_visible_ && !is_zero_sized();
|
||||
if (should_show_root_node != is_root_node_shown_) {
|
||||
is_root_node_shown_ = should_show_root_node;
|
||||
if (should_show_root_node) {
|
||||
// Attach nodes to render content and receive input.
|
||||
node_->AddChild(*input_node_);
|
||||
node_->AddChild(*render_node_);
|
||||
} else {
|
||||
node_->DetachChildren();
|
||||
}
|
||||
}
|
||||
return is_root_node_shown_;
|
||||
}
|
||||
|
||||
void ScenicWindow::OnViewControllerDisconnected(zx_status_t status) {
|
||||
view_controller_ = nullptr;
|
||||
delegate_->OnCloseRequest();
|
||||
}
|
||||
|
||||
} // namespace ui
|
@ -1,227 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// 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_WINDOW_H_
|
||||
#define UI_OZONE_PLATFORM_SCENIC_SCENIC_WINDOW_H_
|
||||
|
||||
#include <fidl/fuchsia.ui.input3/cpp/fidl.h>
|
||||
#include <fuchsia/ui/gfx/cpp/fidl.h>
|
||||
#include <fuchsia/ui/input/cpp/fidl.h>
|
||||
#include <fuchsia/ui/views/cpp/fidl.h>
|
||||
#include <lib/ui/scenic/cpp/resources.h>
|
||||
#include <lib/ui/scenic/cpp/session.h>
|
||||
#include <lib/ui/scenic/cpp/view_ref_pair.h>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/component_export.h"
|
||||
#include "base/fuchsia/fidl_event_handler.h"
|
||||
#include "ui/base/ime/fuchsia/keyboard_client.h"
|
||||
#include "ui/events/fuchsia/input_event_sink.h"
|
||||
#include "ui/events/fuchsia/pointer_events_handler.h"
|
||||
#include "ui/gfx/geometry/rect.h"
|
||||
#include "ui/gfx/geometry/size.h"
|
||||
#include "ui/gfx/geometry/size_f.h"
|
||||
#include "ui/gfx/native_widget_types.h"
|
||||
#include "ui/ozone/platform/scenic/safe_presenter.h"
|
||||
#include "ui/platform_window/platform_window.h"
|
||||
#include "ui/platform_window/platform_window_delegate.h"
|
||||
#include "ui/platform_window/platform_window_init_properties.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
class ScenicWindowDelegate;
|
||||
class ScenicWindowManager;
|
||||
|
||||
class COMPONENT_EXPORT(OZONE) ScenicWindow final : public PlatformWindow,
|
||||
public InputEventSink {
|
||||
public:
|
||||
// Both |window_manager| and |delegate| must outlive the ScenicWindow.
|
||||
// |view_token| is passed to Scenic to attach the view to the view tree.
|
||||
// |view_ref_pair| will be associated with this window's View, and used to
|
||||
// identify it when calling out to other services (e.g. the SemanticsManager).
|
||||
ScenicWindow(ScenicWindowManager* window_manager,
|
||||
PlatformWindowDelegate* delegate,
|
||||
PlatformWindowInitProperties properties);
|
||||
~ScenicWindow() override;
|
||||
|
||||
ScenicWindow(const ScenicWindow&) = delete;
|
||||
ScenicWindow& operator=(const ScenicWindow&) = delete;
|
||||
|
||||
// Returns a ViewRef that may be used to refer to this window's View, when
|
||||
// interacting with View-based services such as the SemanticsManager.
|
||||
fuchsia::ui::views::ViewRef CloneViewRef();
|
||||
|
||||
// ui::PlatformWindow implementation.
|
||||
gfx::Rect GetBoundsInPixels() const override;
|
||||
void SetBoundsInPixels(const gfx::Rect& bounds) override;
|
||||
gfx::Rect GetBoundsInDIP() const override;
|
||||
void SetBoundsInDIP(const gfx::Rect& bounds) override;
|
||||
void SetTitle(const std::u16string& title) override;
|
||||
void Show(bool inactive) override;
|
||||
void Hide() override;
|
||||
void Close() override;
|
||||
bool IsVisible() const override;
|
||||
void PrepareForShutdown() override;
|
||||
void SetCapture() override;
|
||||
void ReleaseCapture() override;
|
||||
bool HasCapture() const override;
|
||||
void SetFullscreen(bool fullscreen, int64_t target_display_id) override;
|
||||
void Maximize() override;
|
||||
void Minimize() override;
|
||||
void Restore() override;
|
||||
PlatformWindowState GetPlatformWindowState() const override;
|
||||
void Activate() override;
|
||||
void Deactivate() override;
|
||||
void SetUseNativeFrame(bool use_native_frame) override;
|
||||
bool ShouldUseNativeFrame() const override;
|
||||
void SetCursor(scoped_refptr<PlatformCursor> cursor) override;
|
||||
void MoveCursorTo(const gfx::Point& location) override;
|
||||
void ConfineCursorToBounds(const gfx::Rect& bounds) override;
|
||||
void SetRestoredBoundsInDIP(const gfx::Rect& bounds) override;
|
||||
gfx::Rect GetRestoredBoundsInDIP() const override;
|
||||
void SetWindowIcons(const gfx::ImageSkia& window_icon,
|
||||
const gfx::ImageSkia& app_icon) override;
|
||||
void SizeConstraintsChanged() override;
|
||||
|
||||
// Used by ScenicGpuHost to embed the View identified by |token| into the
|
||||
// render node, causing its contents to be displayed in this window.
|
||||
void AttachSurfaceView(fuchsia::ui::views::ViewHolderToken token);
|
||||
|
||||
// Used by OzoneScenicPlatform to determine whether to enable on-screen
|
||||
// keyboard features when creating the InputMethod for the window.
|
||||
bool is_virtual_keyboard_enabled() const {
|
||||
return is_virtual_keyboard_enabled_;
|
||||
}
|
||||
|
||||
private:
|
||||
// ui::InputEventSink implementation, used to scale input event locations
|
||||
// according to the View's current device pixel ratio.
|
||||
void DispatchEvent(ui::Event* event) override;
|
||||
|
||||
// Callbacks for |scenic_session_|.
|
||||
void OnScenicError(zx_status_t status);
|
||||
void OnScenicEvents(std::vector<fuchsia::ui::scenic::Event> events);
|
||||
|
||||
// Called from OnScenicEvents() to handle view properties and metrics changes.
|
||||
void OnViewAttachedChanged(bool is_view_attached);
|
||||
void OnViewMetrics(const fuchsia::ui::gfx::Metrics& metrics);
|
||||
void OnViewProperties(const fuchsia::ui::gfx::ViewProperties& properties);
|
||||
|
||||
// Called from OnScenicEvents() to handle focus change and input events.
|
||||
void OnInputEvent(const fuchsia::ui::input::InputEvent& event);
|
||||
|
||||
// Hanging gets from |view_ref_focused_|.
|
||||
void OnViewRefFocusedWatchResult(fuchsia::ui::views::FocusState focus_state);
|
||||
|
||||
// Sizes the Scenic nodes based on the View dimensions, and device pixel
|
||||
// ratio, and signals the dimensions change to the window delegate.
|
||||
void UpdateSize();
|
||||
|
||||
// Attaches or detaches the root node to match the visibility and dimensions
|
||||
// of the window's View. Returns true if the root node is currently visible.
|
||||
bool UpdateRootNodeVisibility();
|
||||
|
||||
// Returns true if the View has zero-sized dimensions set.
|
||||
bool is_zero_sized() const {
|
||||
return view_properties_ && ((view_properties_->bounding_box.max.x ==
|
||||
view_properties_->bounding_box.min.x) ||
|
||||
(view_properties_->bounding_box.max.y ==
|
||||
view_properties_->bounding_box.min.y));
|
||||
}
|
||||
|
||||
void OnViewControllerDisconnected(zx_status_t status);
|
||||
|
||||
ScenicWindowManager* const manager_;
|
||||
PlatformWindowDelegate* const delegate_;
|
||||
ScenicWindowDelegate* const scenic_window_delegate_;
|
||||
gfx::AcceleratedWidget const window_id_;
|
||||
|
||||
// Handle to a kernel object which identifies this window's View
|
||||
// across the system. ViewRef consumers can access the handle by
|
||||
// calling CloneViewRef().
|
||||
const fuchsia::ui::views::ViewRef view_ref_;
|
||||
|
||||
// Used to coordinate window closure requests with the shell.
|
||||
fuchsia::element::ViewControllerPtr view_controller_;
|
||||
|
||||
fidl::Client<fuchsia_ui_input3::Keyboard> keyboard_fidl_client_;
|
||||
base::FidlErrorEventLogger<fuchsia_ui_input3::Keyboard>
|
||||
fidl_error_event_logger_;
|
||||
std::unique_ptr<KeyboardClient> keyboard_client_;
|
||||
|
||||
// React to view-focus coming and going.
|
||||
fuchsia::ui::views::ViewRefFocusedPtr view_ref_focused_;
|
||||
|
||||
// Accept touch and mouse events.
|
||||
absl::optional<PointerEventsHandler> pointer_handler_;
|
||||
|
||||
// Scenic session used for all drawing operations in this View.
|
||||
absl::optional<scenic::Session> scenic_session_;
|
||||
|
||||
// Used for safely queueing Present() operations on |scenic_session_|.
|
||||
absl::optional<SafePresenter> safe_presenter_;
|
||||
|
||||
// The view resource in |scenic_session_|.
|
||||
absl::optional<scenic::View> view_;
|
||||
|
||||
// Entity node for the |view_|.
|
||||
absl::optional<scenic::EntityNode> node_;
|
||||
|
||||
// Node in |scenic_session_| for receiving input that hits within our View.
|
||||
absl::optional<scenic::ShapeNode> input_node_;
|
||||
|
||||
// Node in |scenic_session_| for rendering (hit testing disabled).
|
||||
absl::optional<scenic::EntityNode> render_node_;
|
||||
|
||||
// Holds the View into which the GPU processes composites the window's
|
||||
// contents.
|
||||
std::unique_ptr<scenic::ViewHolder> surface_view_holder_;
|
||||
|
||||
// The scale between logical pixels and physical pixels, set based on the
|
||||
// fuchsia::ui::gfx::Metrics event. It's used to calculate dimensions of the
|
||||
// view in physical pixels in UpdateSize(). This value doesn't affect the
|
||||
// device_scale_factor reported by ScenicScreen for the corresponding display
|
||||
// (currently always 1.0, see crbug.com/1215330).
|
||||
float device_pixel_ratio_ = 0.f;
|
||||
|
||||
// Current view size in DIPs.
|
||||
gfx::SizeF size_dips_;
|
||||
|
||||
// Current view size in device pixels. The size is set to
|
||||
// |PlatformWindowInitProperties.bounds.size()| value until Show() is called
|
||||
// for the first time. After that the size is set to the size of the
|
||||
// corresponding Scenic view.
|
||||
gfx::Rect bounds_;
|
||||
|
||||
// Holds the contents of the fuchsia.ui.gfx.Event.view_properties_changed
|
||||
// most recently received for the View, if any.
|
||||
absl::optional<fuchsia::ui::gfx::ViewProperties> view_properties_;
|
||||
|
||||
// False if the View for this window is detached from the View tree, in which
|
||||
// case it is definitely not visible.
|
||||
bool is_visible_ = false;
|
||||
|
||||
// True if the View occupies the full screen.
|
||||
bool is_fullscreen_ = false;
|
||||
|
||||
// True if the on-screen virtual keyboard is available for this window.
|
||||
bool is_virtual_keyboard_enabled_ = false;
|
||||
|
||||
// True if the root node is attached to the View, to be rendered.
|
||||
bool is_root_node_shown_ = false;
|
||||
|
||||
// True if |view_| is currently attached to a scene.
|
||||
bool is_view_attached_ = false;
|
||||
|
||||
// True if SetCapture() was called. Currently does not reflect capture state
|
||||
// in Scenic.
|
||||
// TODO(crbug.com/1231516): Use Scenic capture APIs.
|
||||
bool has_capture_ = false;
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
|
||||
#endif // UI_OZONE_PLATFORM_SCENIC_SCENIC_WINDOW_H_
|
@ -1,182 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// 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_window_canvas.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "base/fuchsia/fuchsia_logging.h"
|
||||
#include "base/memory/read_only_shared_memory_region.h"
|
||||
#include "base/memory/writable_shared_memory_region.h"
|
||||
#include "skia/ext/legacy_display_globals.h"
|
||||
#include "ui/gfx/geometry/size_f.h"
|
||||
#include "ui/gfx/geometry/skia_conversions.h"
|
||||
#include "ui/gfx/vsync_provider.h"
|
||||
#include "ui/ozone/platform/scenic/scenic_window.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
// How long we want to wait for release-fence from scenic for previous frames.
|
||||
constexpr base::TimeDelta kFrameReleaseTimeout = base::Milliseconds(500);
|
||||
|
||||
ScenicWindowCanvas::Frame::Frame() = default;
|
||||
ScenicWindowCanvas::Frame::~Frame() = default;
|
||||
|
||||
void ScenicWindowCanvas::Frame::Initialize(gfx::Size size,
|
||||
scenic::Session* scenic) {
|
||||
size_t bytes_per_row =
|
||||
size.width() * SkColorTypeBytesPerPixel(kN32_SkColorType);
|
||||
size_t buffer_size = bytes_per_row * size.height();
|
||||
|
||||
base::WritableSharedMemoryRegion memory_region =
|
||||
base::WritableSharedMemoryRegion::Create(buffer_size);
|
||||
memory_mapping = memory_region.Map();
|
||||
|
||||
if (!memory_mapping.IsValid()) {
|
||||
LOG(WARNING) << "Failed to map memory for ScenicWindowCanvas.";
|
||||
memory_mapping = base::WritableSharedMemoryMapping();
|
||||
surface.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
auto read_only_memory = base::WritableSharedMemoryRegion::ConvertToReadOnly(
|
||||
std::move(memory_region));
|
||||
auto memory_handle =
|
||||
base::ReadOnlySharedMemoryRegion::TakeHandleForSerialization(
|
||||
std::move(read_only_memory));
|
||||
scenic_memory = std::make_unique<scenic::Memory>(
|
||||
scenic, memory_handle.PassPlatformHandle(), buffer_size,
|
||||
fuchsia::images::MemoryType::HOST_MEMORY);
|
||||
SkSurfaceProps props = skia::LegacyDisplayGlobals::GetSkSurfaceProps();
|
||||
surface = SkSurfaces::WrapPixels(
|
||||
SkImageInfo::MakeN32Premul(size.width(), size.height()),
|
||||
memory_mapping.memory(), bytes_per_row, &props);
|
||||
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_mapping.memory()) +
|
||||
i.rect().x() * SkColorTypeBytesPerPixel(kN32_SkColorType) +
|
||||
i.rect().y() * stride;
|
||||
frame.surface->readPixels(
|
||||
SkImageInfo::MakeN32Premul(i.rect().width(), i.rect().height()),
|
||||
dst_ptr, stride, i.rect().x(), i.rect().y());
|
||||
}
|
||||
dirty_region.setEmpty();
|
||||
}
|
||||
|
||||
ScenicWindowCanvas::ScenicWindowCanvas(ScenicSurface* scenic_surface)
|
||||
: scenic_surface_(scenic_surface) {}
|
||||
|
||||
ScenicWindowCanvas::~ScenicWindowCanvas() = default;
|
||||
|
||||
void ScenicWindowCanvas::ResizeCanvas(const gfx::Size& viewport_size,
|
||||
float scale) {
|
||||
viewport_size_ = viewport_size;
|
||||
viewport_size_.SetToMax(gfx::Size(1, 1));
|
||||
|
||||
// Allocate new buffers with the new size.
|
||||
for (int i = 0; i < kNumBuffers; ++i) {
|
||||
frames_[i].Initialize(viewport_size_, scenic_surface_->scenic_session());
|
||||
}
|
||||
}
|
||||
|
||||
SkCanvas* ScenicWindowCanvas::GetCanvas() {
|
||||
if (viewport_size_.IsEmpty() || frames_[current_frame_].is_empty())
|
||||
return nullptr;
|
||||
|
||||
// Wait for the buffer to become available. This call has to be blocking
|
||||
// because GetSurface() and PresentCanvas() are synchronous.
|
||||
//
|
||||
// TODO(sergeyu): Consider updating SurfaceOzoneCanvas interface to allow
|
||||
// asynchronous PresentCanvas() and then wait for release-fence before
|
||||
// PresentCanvas() completes.
|
||||
if (frames_[current_frame_].release_fence) {
|
||||
auto status = frames_[current_frame_].release_fence.wait_one(
|
||||
ZX_EVENT_SIGNALED,
|
||||
zx::deadline_after(zx::duration(kFrameReleaseTimeout.InNanoseconds())),
|
||||
nullptr);
|
||||
if (status == ZX_ERR_TIMED_OUT) {
|
||||
// Timeout here indicates that Scenic is most likely broken. If it still
|
||||
// works, then in the worst case returning before |release_fence| is
|
||||
// signaled will cause screen tearing.
|
||||
LOG(WARNING) << "Release fence from previous frame timed out after 500ms";
|
||||
} else {
|
||||
ZX_CHECK(status == ZX_OK, status);
|
||||
}
|
||||
}
|
||||
|
||||
return frames_[current_frame_].surface->getCanvas();
|
||||
}
|
||||
|
||||
void ScenicWindowCanvas::PresentCanvas(const gfx::Rect& damage) {
|
||||
// Subtract |damage| from the dirty region in the current frame since it's
|
||||
// been repainted.
|
||||
SkIRect sk_damage = gfx::RectToSkIRect(damage);
|
||||
frames_[current_frame_].dirty_region.op(sk_damage, SkRegion::kDifference_Op);
|
||||
|
||||
// Copy dirty region from the previous buffer to make sure the whole frame
|
||||
// is up to date.
|
||||
int prev_frame =
|
||||
current_frame_ == 0 ? (kNumBuffers - 1) : (current_frame_ - 1);
|
||||
frames_[current_frame_].CopyDirtyRegionFrom(frames_[prev_frame]);
|
||||
|
||||
// |damage| rect was updated in the current frame. It means that the rect is
|
||||
// no longer valid in all other buffers. Add |damage| to |dirty_region| in all
|
||||
// buffers except the current one.
|
||||
for (int i = 0; i < kNumBuffers; ++i) {
|
||||
if (i != current_frame_) {
|
||||
frames_[i].dirty_region.op(sk_damage, SkRegion::kUnion_Op);
|
||||
}
|
||||
}
|
||||
|
||||
// Create image that wraps the buffer and attach it as texture for the node.
|
||||
fuchsia::images::ImageInfo info;
|
||||
info.width = viewport_size_.width();
|
||||
info.height = viewport_size_.height();
|
||||
info.stride =
|
||||
viewport_size_.width() * SkColorTypeBytesPerPixel(kN32_SkColorType);
|
||||
scenic::Image image(*frames_[current_frame_].scenic_memory, 0,
|
||||
std::move(info));
|
||||
// TODO(spang): Consider using ImagePipe for consistency with vulkan path.
|
||||
scenic_surface_->SetTextureToImage(image);
|
||||
|
||||
// Create release fence for the current buffer or reset it if it already
|
||||
// exists.
|
||||
if (!frames_[current_frame_].release_fence) {
|
||||
auto status = zx::event::create(
|
||||
/*options=*/0u, &(frames_[current_frame_].release_fence));
|
||||
ZX_CHECK(status == ZX_OK, status);
|
||||
} else {
|
||||
auto status = frames_[current_frame_].release_fence.signal(
|
||||
/*clear_mask=*/ZX_EVENT_SIGNALED, /*set_maks=*/0);
|
||||
ZX_CHECK(status == ZX_OK, status);
|
||||
}
|
||||
|
||||
// Add release-fence for the Present2() call below. The fence is used in
|
||||
// GetCanvas() to ensure that we reuse the buffer only after it's released
|
||||
// from scenic.
|
||||
zx::event release_fence_dup;
|
||||
auto status = frames_[current_frame_].release_fence.duplicate(
|
||||
ZX_RIGHT_SAME_RIGHTS, &release_fence_dup);
|
||||
ZX_CHECK(status == ZX_OK, status);
|
||||
scenic_surface_->scenic_session()->EnqueueReleaseFence(
|
||||
std::move(release_fence_dup));
|
||||
scenic_surface_->safe_presenter()->QueuePresent();
|
||||
|
||||
// Move to the next buffer.
|
||||
current_frame_ = (current_frame_ + 1) % kNumBuffers;
|
||||
}
|
||||
|
||||
std::unique_ptr<gfx::VSyncProvider> ScenicWindowCanvas::CreateVSyncProvider() {
|
||||
// TODO(crbug.com/829980): Implement VSyncProvider. It can be implemented by
|
||||
// observing FuturePresentationTimes returned from
|
||||
// scenic::Session::Present2().
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace ui
|
@ -1,95 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// 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_WINDOW_CANVAS_H_
|
||||
#define UI_OZONE_PLATFORM_SCENIC_SCENIC_WINDOW_CANVAS_H_
|
||||
|
||||
#include <lib/ui/scenic/cpp/resources.h>
|
||||
#include <memory>
|
||||
|
||||
#include "base/memory/shared_memory_mapping.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_surface.h"
|
||||
#include "ui/ozone/platform/scenic/scenic_surface_factory.h"
|
||||
#include "ui/ozone/public/surface_ozone_canvas.h"
|
||||
|
||||
class SkSurface;
|
||||
|
||||
namespace scenic {
|
||||
class Session;
|
||||
} // namespace scenic
|
||||
|
||||
namespace ui {
|
||||
|
||||
class ScenicWindow;
|
||||
|
||||
// SurfaceOzoneCanvas implementation for ScenicWindow. It allows to draw on a
|
||||
// ScenicWindow.
|
||||
class ScenicWindowCanvas : public SurfaceOzoneCanvas {
|
||||
public:
|
||||
// |scenic_surface| must outlive the canvas. ScenicSurface owns the
|
||||
// scenic::Session used in this class for all drawing operations.
|
||||
explicit ScenicWindowCanvas(ScenicSurface* scenic_surface);
|
||||
|
||||
ScenicWindowCanvas(const ScenicWindowCanvas&) = delete;
|
||||
ScenicWindowCanvas& operator=(const ScenicWindowCanvas&) = delete;
|
||||
|
||||
~ScenicWindowCanvas() override;
|
||||
|
||||
// SurfaceOzoneCanvas implementation.
|
||||
void ResizeCanvas(const gfx::Size& viewport_size, float scale) override;
|
||||
SkCanvas* GetCanvas() override;
|
||||
void PresentCanvas(const gfx::Rect& damage) override;
|
||||
std::unique_ptr<gfx::VSyncProvider> CreateVSyncProvider() override;
|
||||
|
||||
private:
|
||||
// Use 2 buffers: one is shown on the screen while the other is used to render
|
||||
// the next frame.
|
||||
static const int kNumBuffers = 2;
|
||||
|
||||
struct Frame {
|
||||
Frame();
|
||||
~Frame();
|
||||
|
||||
// Allocates and maps memory for a frame of |size| (in physical in pixels)
|
||||
// and then registers it with |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 !surface; }
|
||||
|
||||
// Shared memory for the buffer.
|
||||
base::WritableSharedMemoryMapping memory_mapping;
|
||||
|
||||
// Scenic Memory resource for |memory_region|.
|
||||
std::unique_ptr<scenic::Memory> scenic_memory;
|
||||
|
||||
// SkSurface that wraps |memory_mapping|.
|
||||
sk_sp<SkSurface> surface;
|
||||
|
||||
// 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.
|
||||
SkRegion dirty_region;
|
||||
};
|
||||
|
||||
Frame frames_[kNumBuffers];
|
||||
|
||||
// Buffer index in |frames_| for the frame that's currently being rendered.
|
||||
int current_frame_ = 0;
|
||||
|
||||
// View size in device pixels.
|
||||
gfx::Size viewport_size_;
|
||||
|
||||
ScenicSurface* const scenic_surface_;
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
|
||||
#endif // UI_OZONE_PLATFORM_SCENIC_SCENIC_WINDOW_CANVAS_H_
|
@ -1,57 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// 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_window_manager.h"
|
||||
|
||||
#include <lib/sys/cpp/component_context.h>
|
||||
#include <memory>
|
||||
|
||||
#include "base/fuchsia/fuchsia_logging.h"
|
||||
#include "base/fuchsia/process_context.h"
|
||||
#include "ui/ozone/platform/scenic/ozone_platform_scenic.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
ScenicWindowManager::ScenicWindowManager() = default;
|
||||
|
||||
ScenicWindowManager::~ScenicWindowManager() {
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
void ScenicWindowManager::Shutdown() {
|
||||
DCHECK(windows_.IsEmpty());
|
||||
scenic_ = nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<PlatformScreen> ScenicWindowManager::CreateScreen() {
|
||||
DCHECK(windows_.IsEmpty());
|
||||
return std::make_unique<ScenicScreen>();
|
||||
}
|
||||
|
||||
fuchsia::ui::scenic::Scenic* ScenicWindowManager::GetScenic() {
|
||||
if (!scenic_) {
|
||||
scenic_ = base::ComponentContextForProcess()
|
||||
->svc()
|
||||
->Connect<fuchsia::ui::scenic::Scenic>();
|
||||
scenic_.set_error_handler(base::LogFidlErrorAndExitProcess(
|
||||
FROM_HERE, "fuchsia.ui.scenic.Scenic"));
|
||||
}
|
||||
return scenic_.get();
|
||||
}
|
||||
|
||||
int32_t ScenicWindowManager::AddWindow(ScenicWindow* window) {
|
||||
return windows_.Add(window);
|
||||
}
|
||||
|
||||
void ScenicWindowManager::RemoveWindow(int32_t window_id,
|
||||
ScenicWindow* window) {
|
||||
DCHECK_EQ(window, windows_.Lookup(window_id));
|
||||
windows_.Remove(window_id);
|
||||
}
|
||||
|
||||
ScenicWindow* ScenicWindowManager::GetWindow(int32_t window_id) {
|
||||
return windows_.Lookup(window_id);
|
||||
}
|
||||
|
||||
} // namespace ui
|
@ -1,66 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// 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_WINDOW_MANAGER_H_
|
||||
#define UI_OZONE_PLATFORM_SCENIC_SCENIC_WINDOW_MANAGER_H_
|
||||
|
||||
#include <fuchsia/ui/scenic/cpp/fidl.h>
|
||||
#include <stdint.h>
|
||||
#include <memory>
|
||||
|
||||
#include "base/component_export.h"
|
||||
#include "base/containers/id_map.h"
|
||||
#include "base/threading/thread_checker.h"
|
||||
#include "ui/gfx/native_widget_types.h"
|
||||
#include "ui/ozone/platform/scenic/scenic_screen.h"
|
||||
#include "ui/ozone/public/surface_factory_ozone.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
class ScenicWindow;
|
||||
|
||||
// Window manager is responsible for mapping window IDs to ScenicWindow
|
||||
// instances. Window IDs are integer values that are passed around as
|
||||
// gpu::AcceleratedWidget. The manager is created and owned by
|
||||
// OzonePlatformScenic.
|
||||
//
|
||||
// TODO(sergeyu): Consider updating AcceleratedWidget to store ScenicWindow*
|
||||
// which would remove the need for the IDMap.
|
||||
class COMPONENT_EXPORT(OZONE) ScenicWindowManager {
|
||||
public:
|
||||
ScenicWindowManager();
|
||||
|
||||
ScenicWindowManager(const ScenicWindowManager&) = delete;
|
||||
ScenicWindowManager& operator=(const ScenicWindowManager&) = delete;
|
||||
|
||||
~ScenicWindowManager();
|
||||
|
||||
// Shuts down the window manager.
|
||||
void Shutdown();
|
||||
|
||||
std::unique_ptr<PlatformScreen> CreateScreen();
|
||||
|
||||
// Scenic interface that is used by ScenicWindow instances. The interface
|
||||
// is initialized lazily on the first call and it don't change afterwards.
|
||||
// ScenicWindowManager keeps the ownership.
|
||||
fuchsia::ui::scenic::Scenic* GetScenic();
|
||||
|
||||
// Called by ScenicWindow when a new window instance is created. Returns
|
||||
// window ID for the |window|.
|
||||
int32_t AddWindow(ScenicWindow* window);
|
||||
|
||||
// Called by ScenicWindow destructor to unregister |window|.
|
||||
void RemoveWindow(int32_t window_id, ScenicWindow* window);
|
||||
|
||||
ScenicWindow* GetWindow(int32_t window_id);
|
||||
|
||||
private:
|
||||
base::IDMap<ScenicWindow*> windows_;
|
||||
|
||||
fuchsia::ui::scenic::ScenicPtr scenic_;
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
|
||||
#endif // UI_OZONE_PLATFORM_SCENIC_SCENIC_WINDOW_MANAGER_H_
|
@ -1,650 +0,0 @@
|
||||
// Copyright 2019 The Chromium Authors
|
||||
// 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/sysmem_buffer_collection.h"
|
||||
|
||||
#include <fuchsia/sysmem/cpp/fidl.h>
|
||||
|
||||
#include <tuple>
|
||||
|
||||
#include "base/bits.h"
|
||||
#include "base/fuchsia/fuchsia_logging.h"
|
||||
#include "base/fuchsia/koid.h"
|
||||
#include "base/task/current_thread.h"
|
||||
#include "base/task/single_thread_task_runner.h"
|
||||
#include "build/build_config.h"
|
||||
#include "gpu/vulkan/vulkan_device_queue.h"
|
||||
#include "gpu/vulkan/vulkan_function_pointers.h"
|
||||
#include "ui/gfx/buffer_format_util.h"
|
||||
#include "ui/ozone/platform/scenic/scenic_surface_factory.h"
|
||||
#include "ui/ozone/platform/scenic/sysmem_native_pixmap.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
namespace {
|
||||
|
||||
size_t RoundUp(size_t value, size_t alignment) {
|
||||
return ((value + alignment - 1) / alignment) * alignment;
|
||||
}
|
||||
|
||||
VkFormat VkFormatForBufferFormat(gfx::BufferFormat buffer_format) {
|
||||
switch (buffer_format) {
|
||||
case gfx::BufferFormat::YVU_420:
|
||||
return VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM;
|
||||
|
||||
case gfx::BufferFormat::YUV_420_BIPLANAR:
|
||||
return VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
|
||||
|
||||
case gfx::BufferFormat::R_8:
|
||||
return VK_FORMAT_R8_UNORM;
|
||||
|
||||
case gfx::BufferFormat::RG_88:
|
||||
return VK_FORMAT_R8G8_UNORM;
|
||||
|
||||
case gfx::BufferFormat::BGRA_8888:
|
||||
case gfx::BufferFormat::BGRX_8888:
|
||||
return VK_FORMAT_B8G8R8A8_UNORM;
|
||||
|
||||
case gfx::BufferFormat::RGBA_8888:
|
||||
case gfx::BufferFormat::RGBX_8888:
|
||||
return VK_FORMAT_R8G8B8A8_UNORM;
|
||||
|
||||
default:
|
||||
NOTREACHED();
|
||||
return VK_FORMAT_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
size_t GetBytesPerPixel(gfx::BufferFormat buffer_format) {
|
||||
switch (buffer_format) {
|
||||
case gfx::BufferFormat::YVU_420:
|
||||
case gfx::BufferFormat::YUV_420_BIPLANAR:
|
||||
case gfx::BufferFormat::R_8:
|
||||
return 1U;
|
||||
|
||||
case gfx::BufferFormat::RG_88:
|
||||
return 2U;
|
||||
|
||||
case gfx::BufferFormat::BGRA_8888:
|
||||
case gfx::BufferFormat::BGRX_8888:
|
||||
case gfx::BufferFormat::RGBA_8888:
|
||||
case gfx::BufferFormat::RGBX_8888:
|
||||
return 4U;
|
||||
|
||||
default:
|
||||
NOTREACHED();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsYuvVkFormat(VkFormat format) {
|
||||
switch (format) {
|
||||
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
|
||||
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
|
||||
return true;
|
||||
case VK_FORMAT_R8_UNORM:
|
||||
case VK_FORMAT_R8G8_UNORM:
|
||||
case VK_FORMAT_B8G8R8A8_UNORM:
|
||||
case VK_FORMAT_R8G8B8A8_UNORM:
|
||||
return false;
|
||||
default:
|
||||
NOTREACHED();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
VkFormatFeatureFlags GetFormatFeatureFlagsFromUsage(VkImageUsageFlags usage) {
|
||||
VkFormatFeatureFlags result = {};
|
||||
if (usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) {
|
||||
result |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT;
|
||||
}
|
||||
if (usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT) {
|
||||
result |= VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
|
||||
}
|
||||
if (usage & VK_IMAGE_USAGE_SAMPLED_BIT) {
|
||||
result |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
|
||||
}
|
||||
if (usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
|
||||
result |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
|
||||
}
|
||||
if (usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
|
||||
result |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
}
|
||||
if (usage & VK_IMAGE_USAGE_STORAGE_BIT) {
|
||||
result |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
VkImageFormatConstraintsInfoFUCHSIA GetDefaultImageFormatConstraintsInfo(
|
||||
const VkImageCreateInfo& create_info) {
|
||||
DCHECK(create_info.format != VK_FORMAT_UNDEFINED);
|
||||
DCHECK(create_info.usage != 0);
|
||||
|
||||
static const VkSysmemColorSpaceFUCHSIA kSrgbColorSpace = {
|
||||
VK_STRUCTURE_TYPE_SYSMEM_COLOR_SPACE_FUCHSIA, nullptr,
|
||||
static_cast<uint32_t>(fuchsia::sysmem::ColorSpaceType::SRGB)};
|
||||
|
||||
static const VkSysmemColorSpaceFUCHSIA kYuvDefaultColorSpaces[] = {
|
||||
{VK_STRUCTURE_TYPE_SYSMEM_COLOR_SPACE_FUCHSIA, nullptr,
|
||||
static_cast<uint32_t>(fuchsia::sysmem::ColorSpaceType::REC709)},
|
||||
{VK_STRUCTURE_TYPE_SYSMEM_COLOR_SPACE_FUCHSIA, nullptr,
|
||||
static_cast<uint32_t>(fuchsia::sysmem::ColorSpaceType::REC601_NTSC)},
|
||||
{VK_STRUCTURE_TYPE_SYSMEM_COLOR_SPACE_FUCHSIA, nullptr,
|
||||
static_cast<uint32_t>(
|
||||
fuchsia::sysmem::ColorSpaceType::REC601_NTSC_FULL_RANGE)},
|
||||
{VK_STRUCTURE_TYPE_SYSMEM_COLOR_SPACE_FUCHSIA, nullptr,
|
||||
static_cast<uint32_t>(fuchsia::sysmem::ColorSpaceType::REC601_PAL)},
|
||||
{VK_STRUCTURE_TYPE_SYSMEM_COLOR_SPACE_FUCHSIA, nullptr,
|
||||
static_cast<uint32_t>(
|
||||
fuchsia::sysmem::ColorSpaceType::REC601_PAL_FULL_RANGE)},
|
||||
};
|
||||
|
||||
bool is_yuv = IsYuvVkFormat(create_info.format);
|
||||
|
||||
VkImageFormatConstraintsInfoFUCHSIA format_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_CONSTRAINTS_INFO_FUCHSIA,
|
||||
.pNext = nullptr,
|
||||
.imageCreateInfo = create_info,
|
||||
.requiredFormatFeatures =
|
||||
GetFormatFeatureFlagsFromUsage(create_info.usage),
|
||||
.sysmemPixelFormat = 0u,
|
||||
.colorSpaceCount = static_cast<uint32_t>(
|
||||
is_yuv ? std::size(kYuvDefaultColorSpaces) : 1u),
|
||||
.pColorSpaces = is_yuv ? kYuvDefaultColorSpaces : &kSrgbColorSpace,
|
||||
};
|
||||
return format_info;
|
||||
}
|
||||
|
||||
struct ImageConstraintsInfo {
|
||||
VkImageConstraintsInfoFUCHSIA image_constraints;
|
||||
VkImageFormatConstraintsInfoFUCHSIA format_constraints;
|
||||
|
||||
ImageConstraintsInfo(
|
||||
const VkImageConstraintsInfoFUCHSIA& image_constraints_in,
|
||||
const VkImageFormatConstraintsInfoFUCHSIA& format_constraints_in)
|
||||
: image_constraints(image_constraints_in),
|
||||
format_constraints(format_constraints_in) {
|
||||
image_constraints.pFormatConstraints = &format_constraints;
|
||||
image_constraints.formatConstraintsCount = 1u;
|
||||
}
|
||||
|
||||
ImageConstraintsInfo(ImageConstraintsInfo&& from) = delete;
|
||||
ImageConstraintsInfo(const ImageConstraintsInfo&) = delete;
|
||||
ImageConstraintsInfo& operator=(const ImageConstraintsInfo&) = delete;
|
||||
};
|
||||
|
||||
std::unique_ptr<ImageConstraintsInfo> InitializeImageConstraintsInfo(
|
||||
const VkImageCreateInfo& vk_image_info,
|
||||
bool allow_protected_memory) {
|
||||
VkImageFormatConstraintsInfoFUCHSIA format_constraints =
|
||||
GetDefaultImageFormatConstraintsInfo(vk_image_info);
|
||||
VkImageConstraintsInfoFUCHSIA image_constraints = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_CONSTRAINTS_INFO_FUCHSIA,
|
||||
.pNext = nullptr,
|
||||
.bufferCollectionConstraints =
|
||||
VkBufferCollectionConstraintsInfoFUCHSIA{
|
||||
.sType =
|
||||
VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CONSTRAINTS_INFO_FUCHSIA,
|
||||
.pNext = nullptr,
|
||||
.minBufferCount = 1u,
|
||||
// Using the default value (0) for the fields below means that
|
||||
// there is no other constraints except for the minimum buffer
|
||||
// count.
|
||||
.maxBufferCount = 0u,
|
||||
.minBufferCountForCamping = 0u,
|
||||
.minBufferCountForDedicatedSlack = 0u,
|
||||
.minBufferCountForSharedSlack = 0u,
|
||||
},
|
||||
// TODO(crbug.com/1289315): Instead of always allowing protected
|
||||
// memory, Chrome should query if the Vulkan physical device
|
||||
// supports protected memory and only set the flag if it is
|
||||
// supported.
|
||||
.flags = allow_protected_memory
|
||||
? VK_IMAGE_CONSTRAINTS_INFO_PROTECTED_OPTIONAL_FUCHSIA
|
||||
: 0u,
|
||||
};
|
||||
|
||||
return std::make_unique<ImageConstraintsInfo>(image_constraints,
|
||||
format_constraints);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
bool SysmemBufferCollection::IsNativePixmapConfigSupported(
|
||||
gfx::BufferFormat format,
|
||||
gfx::BufferUsage usage) {
|
||||
switch (format) {
|
||||
case gfx::BufferFormat::YUV_420_BIPLANAR:
|
||||
case gfx::BufferFormat::R_8:
|
||||
case gfx::BufferFormat::RG_88:
|
||||
case gfx::BufferFormat::RGBA_8888:
|
||||
case gfx::BufferFormat::RGBX_8888:
|
||||
case gfx::BufferFormat::BGRA_8888:
|
||||
case gfx::BufferFormat::BGRX_8888:
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
switch (usage) {
|
||||
case gfx::BufferUsage::SCANOUT:
|
||||
case gfx::BufferUsage::GPU_READ:
|
||||
break;
|
||||
|
||||
case gfx::BufferUsage::SCANOUT_CPU_READ_WRITE:
|
||||
case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE:
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
SysmemBufferCollection::SysmemBufferCollection() = default;
|
||||
|
||||
bool SysmemBufferCollection::Initialize(
|
||||
fuchsia::sysmem::Allocator_Sync* allocator,
|
||||
ScenicSurfaceFactory* scenic_surface_factory,
|
||||
zx::eventpair handle,
|
||||
zx::channel sysmem_token,
|
||||
gfx::Size size,
|
||||
gfx::BufferFormat format,
|
||||
gfx::BufferUsage usage,
|
||||
VkDevice vk_device,
|
||||
size_t min_buffer_count,
|
||||
bool register_with_image_pipe) {
|
||||
DCHECK(IsNativePixmapConfigSupported(format, usage));
|
||||
DCHECK(!collection_);
|
||||
DCHECK(!vk_buffer_collection_);
|
||||
|
||||
handle_ = std::move(handle);
|
||||
auto koid = base::GetKoid(handle_);
|
||||
if (!koid)
|
||||
return false;
|
||||
id_ = koid.value();
|
||||
|
||||
// Currently all supported |usage| values require GPU access, which requires
|
||||
// a valid VkDevice.
|
||||
if (vk_device == VK_NULL_HANDLE)
|
||||
return false;
|
||||
|
||||
if (size.IsEmpty()) {
|
||||
// Buffer collection that doesn't have explicit size is expected to be
|
||||
// shared with other participants, who will determine the actual image size.
|
||||
DCHECK(sysmem_token);
|
||||
|
||||
// Set nominal size of 1x1, which will be used only for
|
||||
// vkSetBufferCollectionConstraintsFUCHSIA(). The actual size of the
|
||||
// allocated buffers is determined by constraints set by other sysmem
|
||||
// clients for the same collection. Size of the Vulkan image is determined
|
||||
// by the values passed to CreateVkImage().
|
||||
min_size_ = gfx::Size(1, 1);
|
||||
} else {
|
||||
min_size_ = size;
|
||||
}
|
||||
|
||||
format_ = format;
|
||||
usage_ = usage;
|
||||
vk_device_ = vk_device;
|
||||
is_protected_ = false;
|
||||
|
||||
if (register_with_image_pipe) {
|
||||
overlay_view_task_runner_ =
|
||||
base::SingleThreadTaskRunner::GetCurrentDefault();
|
||||
scenic_overlay_view_ = std::make_unique<ScenicOverlayView>(
|
||||
scenic_surface_factory->CreateScenicSession());
|
||||
}
|
||||
|
||||
fuchsia::sysmem::BufferCollectionTokenSyncPtr collection_token;
|
||||
if (sysmem_token) {
|
||||
collection_token.Bind(std::move(sysmem_token));
|
||||
} else {
|
||||
zx_status_t status =
|
||||
allocator->AllocateSharedCollection(collection_token.NewRequest());
|
||||
if (status != ZX_OK) {
|
||||
ZX_DLOG(ERROR, status)
|
||||
<< "fuchsia.sysmem.Allocator.AllocateSharedCollection()";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return InitializeInternal(allocator, std::move(collection_token),
|
||||
min_buffer_count);
|
||||
}
|
||||
|
||||
scoped_refptr<gfx::NativePixmap> SysmemBufferCollection::CreateNativePixmap(
|
||||
gfx::NativePixmapHandle handle,
|
||||
gfx::Size size) {
|
||||
CHECK_LT(handle.buffer_index, num_buffers());
|
||||
|
||||
DCHECK_EQ(base::GetRelatedKoid(handle.buffer_collection_handle).value(), id_);
|
||||
handle.ram_coherency =
|
||||
buffers_info_.settings.buffer_settings.coherency_domain ==
|
||||
fuchsia::sysmem::CoherencyDomain::RAM;
|
||||
|
||||
// `handle.planes` need to be filled in only for mappable buffers.
|
||||
if (!is_mappable())
|
||||
return new SysmemNativePixmap(this, std::move(handle), size);
|
||||
|
||||
zx::vmo main_plane_vmo;
|
||||
DCHECK(buffers_info_.buffers[handle.buffer_index].vmo.is_valid());
|
||||
zx_status_t status = buffers_info_.buffers[handle.buffer_index].vmo.duplicate(
|
||||
ZX_RIGHT_SAME_RIGHTS, &main_plane_vmo);
|
||||
if (status != ZX_OK) {
|
||||
ZX_DLOG(ERROR, status) << "zx_handle_duplicate";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const fuchsia::sysmem::ImageFormatConstraints& format =
|
||||
buffers_info_.settings.image_format_constraints;
|
||||
|
||||
// The logic should match LogicalBufferCollection::Allocate().
|
||||
size_t stride =
|
||||
RoundUp(std::max(static_cast<size_t>(format.min_bytes_per_row),
|
||||
size.width() * GetBytesPerPixel(format_)),
|
||||
format.bytes_per_row_divisor);
|
||||
size_t plane_offset =
|
||||
buffers_info_.buffers[handle.buffer_index].vmo_usable_start;
|
||||
size_t plane_size = stride * size.height();
|
||||
handle.planes.emplace_back(stride, plane_offset, plane_size,
|
||||
std::move(main_plane_vmo));
|
||||
|
||||
// For YUV images add a second plane.
|
||||
if (format_ == gfx::BufferFormat::YUV_420_BIPLANAR) {
|
||||
size_t uv_plane_offset = plane_offset + plane_size;
|
||||
size_t uv_plane_size = plane_size / 2;
|
||||
|
||||
zx::vmo uv_plane_vmo;
|
||||
status =
|
||||
handle.planes[0].vmo.duplicate(ZX_RIGHT_SAME_RIGHTS, &uv_plane_vmo);
|
||||
if (status != ZX_OK) {
|
||||
ZX_DLOG(ERROR, status) << "zx_handle_duplicate";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
handle.planes.emplace_back(stride, uv_plane_offset, uv_plane_size,
|
||||
std::move(uv_plane_vmo));
|
||||
DCHECK_LE(uv_plane_offset + uv_plane_size, buffer_size_);
|
||||
}
|
||||
|
||||
return new SysmemNativePixmap(this, std::move(handle), size);
|
||||
}
|
||||
|
||||
bool SysmemBufferCollection::CreateVkImage(size_t buffer_index,
|
||||
VkDevice vk_device,
|
||||
gfx::Size size,
|
||||
VkImage* vk_image,
|
||||
VkImageCreateInfo* vk_image_info,
|
||||
VkDeviceMemory* vk_device_memory,
|
||||
VkDeviceSize* mem_allocation_size) {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(vulkan_thread_checker_);
|
||||
|
||||
if (vk_device_ != vk_device) {
|
||||
DLOG(FATAL) << "Tried to import NativePixmap that was created for a "
|
||||
"different VkDevice.";
|
||||
return false;
|
||||
}
|
||||
|
||||
VkBufferCollectionPropertiesFUCHSIA properties = {
|
||||
VK_STRUCTURE_TYPE_BUFFER_COLLECTION_PROPERTIES_FUCHSIA};
|
||||
if (vkGetBufferCollectionPropertiesFUCHSIA(vk_device_, vk_buffer_collection_,
|
||||
&properties) != VK_SUCCESS) {
|
||||
DLOG(ERROR) << "vkGetBufferCollectionPropertiesFUCHSIA failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
InitializeImageCreateInfo(vk_image_info, size);
|
||||
|
||||
VkBufferCollectionImageCreateInfoFUCHSIA image_format_fuchsia = {
|
||||
VK_STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA,
|
||||
};
|
||||
image_format_fuchsia.collection = vk_buffer_collection_;
|
||||
image_format_fuchsia.index = buffer_index;
|
||||
vk_image_info->pNext = &image_format_fuchsia;
|
||||
|
||||
if (vkCreateImage(vk_device_, vk_image_info, nullptr, vk_image) !=
|
||||
VK_SUCCESS) {
|
||||
DLOG(ERROR) << "Failed to create VkImage.";
|
||||
return false;
|
||||
}
|
||||
|
||||
vk_image_info->pNext = nullptr;
|
||||
|
||||
VkMemoryRequirements requirements;
|
||||
vkGetImageMemoryRequirements(vk_device, *vk_image, &requirements);
|
||||
|
||||
uint32_t viable_memory_types =
|
||||
properties.memoryTypeBits & requirements.memoryTypeBits;
|
||||
uint32_t memory_type = base::bits::CountTrailingZeroBits(viable_memory_types);
|
||||
|
||||
VkMemoryDedicatedAllocateInfoKHR dedicated_allocate = {
|
||||
VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR};
|
||||
dedicated_allocate.image = *vk_image;
|
||||
VkImportMemoryBufferCollectionFUCHSIA buffer_collection_info = {
|
||||
VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA,
|
||||
&dedicated_allocate};
|
||||
buffer_collection_info.collection = vk_buffer_collection_;
|
||||
buffer_collection_info.index = buffer_index;
|
||||
|
||||
VkMemoryAllocateInfo alloc_info = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
&buffer_collection_info};
|
||||
alloc_info.allocationSize = requirements.size;
|
||||
alloc_info.memoryTypeIndex = memory_type;
|
||||
|
||||
if (vkAllocateMemory(vk_device_, &alloc_info, nullptr, vk_device_memory) !=
|
||||
VK_SUCCESS) {
|
||||
DLOG(ERROR) << "Failed to create VkMemory from sysmem buffer.";
|
||||
vkDestroyImage(vk_device_, *vk_image, nullptr);
|
||||
*vk_image = VK_NULL_HANDLE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (vkBindImageMemory(vk_device_, *vk_image, *vk_device_memory, 0u) !=
|
||||
VK_SUCCESS) {
|
||||
DLOG(ERROR) << "Failed to bind sysmem buffer to a VkImage.";
|
||||
vkDestroyImage(vk_device_, *vk_image, nullptr);
|
||||
*vk_image = VK_NULL_HANDLE;
|
||||
vkFreeMemory(vk_device_, *vk_device_memory, nullptr);
|
||||
*vk_device_memory = VK_NULL_HANDLE;
|
||||
return false;
|
||||
}
|
||||
|
||||
*mem_allocation_size = requirements.size;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SysmemBufferCollection::AddOnReleasedCallback(
|
||||
base::OnceClosure on_released) {
|
||||
on_released_.push_back(std::move(on_released));
|
||||
}
|
||||
|
||||
SysmemBufferCollection::~SysmemBufferCollection() {
|
||||
if (vk_buffer_collection_ != VK_NULL_HANDLE) {
|
||||
vkDestroyBufferCollectionFUCHSIA(vk_device_, vk_buffer_collection_,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
if (collection_)
|
||||
collection_->Close();
|
||||
|
||||
if (scenic_overlay_view_ &&
|
||||
!overlay_view_task_runner_->BelongsToCurrentThread()) {
|
||||
overlay_view_task_runner_->DeleteSoon(FROM_HERE,
|
||||
std::move(scenic_overlay_view_));
|
||||
}
|
||||
}
|
||||
|
||||
bool SysmemBufferCollection::InitializeInternal(
|
||||
fuchsia::sysmem::Allocator_Sync* allocator,
|
||||
fuchsia::sysmem::BufferCollectionTokenSyncPtr collection_token,
|
||||
size_t min_buffer_count) {
|
||||
fidl::InterfaceHandle<fuchsia::sysmem::BufferCollectionToken>
|
||||
collection_token_for_vulkan;
|
||||
collection_token->Duplicate(ZX_RIGHT_SAME_RIGHTS,
|
||||
collection_token_for_vulkan.NewRequest());
|
||||
|
||||
// Duplicate one more token for Scenic if this collection can be used as an
|
||||
// overlay.
|
||||
fidl::InterfaceHandle<fuchsia::sysmem::BufferCollectionToken>
|
||||
collection_token_for_scenic;
|
||||
if (scenic_overlay_view_) {
|
||||
collection_token->Duplicate(ZX_RIGHT_SAME_RIGHTS,
|
||||
collection_token_for_scenic.NewRequest());
|
||||
}
|
||||
|
||||
zx_status_t status = collection_token->Sync();
|
||||
if (status != ZX_OK) {
|
||||
ZX_DLOG(ERROR, status) << "fuchsia.sysmem.BufferCollectionToken.Sync()";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (scenic_overlay_view_) {
|
||||
scenic_overlay_view_->Initialize(std::move(collection_token_for_scenic));
|
||||
}
|
||||
|
||||
status = allocator->BindSharedCollection(std::move(collection_token),
|
||||
collection_.NewRequest());
|
||||
if (status != ZX_OK) {
|
||||
ZX_DLOG(ERROR, status) << "fuchsia.sysmem.Allocator.BindSharedCollection()";
|
||||
return false;
|
||||
}
|
||||
|
||||
fuchsia::sysmem::BufferCollectionConstraints constraints;
|
||||
if (is_mappable()) {
|
||||
constraints.usage.cpu =
|
||||
fuchsia::sysmem::cpuUsageRead | fuchsia::sysmem::cpuUsageWrite;
|
||||
|
||||
constraints.has_buffer_memory_constraints = true;
|
||||
constraints.buffer_memory_constraints.ram_domain_supported = true;
|
||||
constraints.buffer_memory_constraints.cpu_domain_supported = true;
|
||||
} else {
|
||||
constraints.usage.none = fuchsia::sysmem::noneUsage;
|
||||
}
|
||||
|
||||
constraints.min_buffer_count = min_buffer_count;
|
||||
constraints.image_format_constraints_count = 0;
|
||||
|
||||
status = collection_->SetConstraints(/*has_constraints=*/true,
|
||||
std::move(constraints));
|
||||
if (status != ZX_OK) {
|
||||
ZX_DLOG(ERROR, status)
|
||||
<< "fuchsia.sysmem.BufferCollection.SetConstraints()";
|
||||
return false;
|
||||
}
|
||||
|
||||
zx::channel token_channel = collection_token_for_vulkan.TakeChannel();
|
||||
VkBufferCollectionCreateInfoFUCHSIA buffer_collection_create_info = {
|
||||
VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CREATE_INFO_FUCHSIA};
|
||||
buffer_collection_create_info.collectionToken = token_channel.get();
|
||||
if (vkCreateBufferCollectionFUCHSIA(vk_device_,
|
||||
&buffer_collection_create_info, nullptr,
|
||||
&vk_buffer_collection_) != VK_SUCCESS) {
|
||||
vk_buffer_collection_ = VK_NULL_HANDLE;
|
||||
DLOG(ERROR) << "vkCreateBufferCollectionFUCHSIA() failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
// vkCreateBufferCollectionFUCHSIA() takes ownership of the token on success.
|
||||
std::ignore = token_channel.release();
|
||||
|
||||
VkImageCreateInfo image_create_info;
|
||||
InitializeImageCreateInfo(&image_create_info, min_size_);
|
||||
|
||||
// TODO(crbug.com/1289315): Instead of always allowing protected memory,
|
||||
// Chrome should query if the Vulkan physical device supports protected
|
||||
// memory and only set the flag if it is supported.
|
||||
auto image_constraints_info = InitializeImageConstraintsInfo(
|
||||
image_create_info, /* allow_protected_memory */ true);
|
||||
|
||||
if (vkSetBufferCollectionImageConstraintsFUCHSIA(
|
||||
vk_device_, vk_buffer_collection_,
|
||||
&image_constraints_info->image_constraints) != VK_SUCCESS) {
|
||||
DLOG(ERROR) << "vkSetBufferCollectionConstraintsFUCHSIA() failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
zx_status_t wait_status;
|
||||
status = collection_->WaitForBuffersAllocated(&wait_status, &buffers_info_);
|
||||
if (status != ZX_OK) {
|
||||
ZX_DLOG(ERROR, status) << "fuchsia.sysmem.BufferCollection failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (wait_status != ZX_OK) {
|
||||
ZX_DLOG(ERROR, status) << "fuchsia.sysmem.BufferCollection::"
|
||||
"WaitForBuffersAllocated() failed.";
|
||||
return false;
|
||||
}
|
||||
|
||||
DCHECK_GE(buffers_info_.buffer_count, min_buffer_count);
|
||||
DCHECK(buffers_info_.settings.has_image_format_constraints);
|
||||
|
||||
buffer_size_ = buffers_info_.settings.buffer_settings.size_bytes;
|
||||
is_protected_ = buffers_info_.settings.buffer_settings.is_secure;
|
||||
|
||||
handle_watch_ =
|
||||
std::make_unique<base::MessagePumpForIO::ZxHandleWatchController>(
|
||||
FROM_HERE);
|
||||
bool watch_result = base::CurrentIOThread::Get()->WatchZxHandle(
|
||||
handle_.get(), /*persistent=*/false, ZX_EVENTPAIR_PEER_CLOSED,
|
||||
handle_watch_.get(), this);
|
||||
|
||||
if (!watch_result) {
|
||||
DLOG(ERROR) << "Failed to add a watcher for sysmem buffer token";
|
||||
return false;
|
||||
}
|
||||
|
||||
// CreateVkImage() should always be called on the same thread, but it may be
|
||||
// different from the thread that called Initialize().
|
||||
DETACH_FROM_THREAD(vulkan_thread_checker_);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SysmemBufferCollection::InitializeImageCreateInfo(
|
||||
VkImageCreateInfo* vk_image_info,
|
||||
gfx::Size size) {
|
||||
*vk_image_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
|
||||
vk_image_info->flags = is_protected_ ? VK_IMAGE_CREATE_PROTECTED_BIT : 0u;
|
||||
vk_image_info->imageType = VK_IMAGE_TYPE_2D;
|
||||
vk_image_info->format = VkFormatForBufferFormat(format_);
|
||||
vk_image_info->extent = VkExtent3D{static_cast<uint32_t>(size.width()),
|
||||
static_cast<uint32_t>(size.height()), 1};
|
||||
vk_image_info->mipLevels = 1;
|
||||
vk_image_info->arrayLayers = 1;
|
||||
vk_image_info->samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
vk_image_info->tiling =
|
||||
is_mappable() ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
|
||||
|
||||
vk_image_info->usage = VK_IMAGE_USAGE_SAMPLED_BIT |
|
||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
|
||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
if (usage_ == gfx::BufferUsage::SCANOUT) {
|
||||
vk_image_info->usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
}
|
||||
|
||||
vk_image_info->sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
vk_image_info->initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
}
|
||||
|
||||
void SysmemBufferCollection::OnZxHandleSignalled(zx_handle_t handle,
|
||||
zx_signals_t signals) {
|
||||
DCHECK_EQ(handle, handle_.get());
|
||||
DCHECK_EQ(signals, ZX_EVENTPAIR_PEER_CLOSED);
|
||||
|
||||
// Keep a reference to `this` to ensure it's not destroyed while calling the
|
||||
// callbacks.
|
||||
scoped_refptr<SysmemBufferCollection> self(this);
|
||||
|
||||
for (auto& callback : on_released_) {
|
||||
std::move(callback).Run();
|
||||
}
|
||||
on_released_.clear();
|
||||
}
|
||||
|
||||
} // namespace ui
|
@ -1,162 +0,0 @@
|
||||
// Copyright 2019 The Chromium Authors
|
||||
// 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_SYSMEM_BUFFER_COLLECTION_H_
|
||||
#define UI_OZONE_PLATFORM_SCENIC_SYSMEM_BUFFER_COLLECTION_H_
|
||||
|
||||
#include <fuchsia/sysmem/cpp/fidl.h>
|
||||
#include <lib/ui/scenic/cpp/session.h>
|
||||
#include <lib/zx/eventpair.h>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
#include "base/functional/callback.h"
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "base/message_loop/message_pump_for_io.h"
|
||||
#include "base/task/single_thread_task_runner.h"
|
||||
#include "base/threading/thread_checker.h"
|
||||
#include "gpu/ipc/common/vulkan_ycbcr_info.h"
|
||||
#include "ui/gfx/buffer_types.h"
|
||||
#include "ui/gfx/geometry/size.h"
|
||||
#include "ui/gfx/native_pixmap_handle.h"
|
||||
#include "ui/ozone/platform/scenic/scenic_overlay_view.h"
|
||||
|
||||
namespace gfx {
|
||||
class NativePixmap;
|
||||
} // namespace gfx
|
||||
|
||||
namespace ui {
|
||||
|
||||
class ScenicSurfaceFactory;
|
||||
|
||||
// SysmemBufferCollection keeps sysmem.BufferCollection interface along with the
|
||||
// corresponding VkBufferCollectionFUCHSIA. It allows to create either
|
||||
// gfx::NativePixmap or VkImage from the buffers in the collection.
|
||||
// A collection can be initialized and used on any thread. CreateVkImage() must
|
||||
// be called on the same thread (because it may be be safe to use
|
||||
// VkBufferCollectionFUCHSIA concurrently on different threads).
|
||||
class SysmemBufferCollection
|
||||
: public base::RefCountedThreadSafe<SysmemBufferCollection>,
|
||||
public base::MessagePumpForIO::ZxHandleWatcher {
|
||||
public:
|
||||
static bool IsNativePixmapConfigSupported(gfx::BufferFormat format,
|
||||
gfx::BufferUsage usage);
|
||||
|
||||
SysmemBufferCollection();
|
||||
|
||||
SysmemBufferCollection(const SysmemBufferCollection&) = delete;
|
||||
SysmemBufferCollection& operator=(const SysmemBufferCollection&) = delete;
|
||||
|
||||
// Initializes the buffer collection and registers it with Vulkan using the
|
||||
// specified |vk_device|. If |token_handle| is null then a new collection
|
||||
// collection is created. |size| may be empty. In that case |token_handle|
|
||||
// must not be null and the image size is determined by the other sysmem
|
||||
// participants.
|
||||
// If |register_with_image_pipe| is true, new ScenicOverlayView instance is
|
||||
// created and |token_handle| gets duplicated to be added to its ImagePipe.
|
||||
bool Initialize(fuchsia::sysmem::Allocator_Sync* allocator,
|
||||
ScenicSurfaceFactory* scenic_surface_factory,
|
||||
zx::eventpair handle,
|
||||
zx::channel sysmem_token,
|
||||
gfx::Size size,
|
||||
gfx::BufferFormat format,
|
||||
gfx::BufferUsage usage,
|
||||
VkDevice vk_device,
|
||||
size_t min_buffer_count,
|
||||
bool register_with_image_pipe);
|
||||
|
||||
void AddOnReleasedCallback(base::OnceClosure on_released);
|
||||
|
||||
// Creates a NativePixmap the buffer with the specified index. Returned
|
||||
// NativePixmap holds a reference to the collection, so the collection is not
|
||||
// deleted until all NativePixmap are destroyed.
|
||||
scoped_refptr<gfx::NativePixmap> CreateNativePixmap(
|
||||
gfx::NativePixmapHandle handle,
|
||||
gfx::Size size);
|
||||
|
||||
// Creates a new Vulkan image for the buffer with the specified index.
|
||||
bool CreateVkImage(size_t buffer_index,
|
||||
VkDevice vk_device,
|
||||
gfx::Size size,
|
||||
VkImage* vk_image,
|
||||
VkImageCreateInfo* vk_image_info,
|
||||
VkDeviceMemory* vk_device_memory,
|
||||
VkDeviceSize* mem_allocation_size);
|
||||
|
||||
zx_koid_t id() const { return id_; }
|
||||
size_t num_buffers() const { return buffers_info_.buffer_count; }
|
||||
gfx::BufferFormat format() const { return format_; }
|
||||
size_t buffer_size() const {
|
||||
return buffers_info_.settings.buffer_settings.size_bytes;
|
||||
}
|
||||
ScenicOverlayView* scenic_overlay_view() {
|
||||
return scenic_overlay_view_ ? scenic_overlay_view_.get() : nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class base::RefCountedThreadSafe<SysmemBufferCollection>;
|
||||
|
||||
~SysmemBufferCollection() override;
|
||||
|
||||
bool InitializeInternal(
|
||||
fuchsia::sysmem::Allocator_Sync* allocator,
|
||||
fuchsia::sysmem::BufferCollectionTokenSyncPtr collection_token,
|
||||
size_t buffers_for_camping);
|
||||
|
||||
void InitializeImageCreateInfo(VkImageCreateInfo* vk_image_info,
|
||||
gfx::Size size);
|
||||
|
||||
bool is_mappable() const {
|
||||
return usage_ == gfx::BufferUsage::SCANOUT_CPU_READ_WRITE ||
|
||||
usage_ == gfx::BufferUsage::GPU_READ_CPU_READ_WRITE;
|
||||
}
|
||||
|
||||
// base::MessagePumpForIO::ZxHandleWatcher implementation.
|
||||
void OnZxHandleSignalled(zx_handle_t handle, zx_signals_t signals) override;
|
||||
|
||||
zx::eventpair handle_;
|
||||
zx_koid_t id_ = 0;
|
||||
|
||||
std::unique_ptr<base::MessagePumpForIO::ZxHandleWatchController>
|
||||
handle_watch_;
|
||||
|
||||
// Image size passed to vkSetBufferCollectionConstraintsFUCHSIA(). The actual
|
||||
// buffers size may be larger depending on constraints set by other
|
||||
// sysmem clients. Size of the image is passed to CreateVkImage().
|
||||
gfx::Size min_size_;
|
||||
|
||||
gfx::BufferFormat format_ = gfx::BufferFormat::RGBA_8888;
|
||||
gfx::BufferUsage usage_ = gfx::BufferUsage::GPU_READ_CPU_READ_WRITE;
|
||||
|
||||
fuchsia::sysmem::BufferCollectionSyncPtr collection_;
|
||||
fuchsia::sysmem::BufferCollectionInfo_2 buffers_info_;
|
||||
|
||||
// Vulkan device for which the collection was initialized.
|
||||
VkDevice vk_device_ = VK_NULL_HANDLE;
|
||||
|
||||
// Handle for the Vulkan object that holds the same logical buffer collection
|
||||
// that is referenced by |collection_|.
|
||||
VkBufferCollectionFUCHSIA vk_buffer_collection_ = VK_NULL_HANDLE;
|
||||
|
||||
// |scenic_overlay_view_| view should be used and deleted on the same thread
|
||||
// as creation.
|
||||
scoped_refptr<base::SingleThreadTaskRunner> overlay_view_task_runner_;
|
||||
// If ScenicOverlayView is created and its ImagePipe is added as a participant
|
||||
// in buffer allocation negotiations, the associated images can be displayed
|
||||
// as overlays.
|
||||
std::unique_ptr<ScenicOverlayView> scenic_overlay_view_;
|
||||
|
||||
// Thread checker used to verify that CreateVkImage() is always called from
|
||||
// the same thread. It may be unsafe to use vk_buffer_collection_ on different
|
||||
// threads.
|
||||
THREAD_CHECKER(vulkan_thread_checker_);
|
||||
|
||||
size_t buffer_size_ = 0;
|
||||
bool is_protected_ = false;
|
||||
|
||||
std::vector<base::OnceClosure> on_released_;
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
|
||||
#endif // UI_OZONE_PLATFORM_SCENIC_SYSMEM_BUFFER_COLLECTION_H_
|
@ -1,139 +0,0 @@
|
||||
// Copyright 2019 The Chromium Authors
|
||||
// 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/sysmem_buffer_manager.h"
|
||||
|
||||
#include <lib/zx/eventpair.h>
|
||||
#include <zircon/rights.h>
|
||||
#include <zircon/types.h>
|
||||
|
||||
#include "base/containers/contains.h"
|
||||
#include "base/fuchsia/fuchsia_logging.h"
|
||||
#include "base/fuchsia/koid.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "ui/gfx/native_pixmap_handle.h"
|
||||
#include "ui/ozone/platform/scenic/sysmem_buffer_collection.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
namespace {
|
||||
|
||||
std::string GetProcessName() {
|
||||
char name[ZX_MAX_NAME_LEN] = {};
|
||||
zx_status_t status =
|
||||
zx::process::self()->get_property(ZX_PROP_NAME, name, sizeof(name));
|
||||
return (status == ZX_OK) ? std::string(name) : "";
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
SysmemBufferManager::SysmemBufferManager(
|
||||
ScenicSurfaceFactory* scenic_surface_factory)
|
||||
: scenic_surface_factory_(scenic_surface_factory) {}
|
||||
|
||||
SysmemBufferManager::~SysmemBufferManager() {
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
void SysmemBufferManager::Initialize(
|
||||
fuchsia::sysmem::AllocatorHandle allocator) {
|
||||
base::AutoLock auto_lock(collections_lock_);
|
||||
DCHECK(collections_.empty());
|
||||
DCHECK(!allocator_);
|
||||
allocator_.Bind(std::move(allocator));
|
||||
allocator_->SetDebugClientInfo(GetProcessName() + "-SysmemBufferManager",
|
||||
base::GetCurrentProcId());
|
||||
}
|
||||
|
||||
void SysmemBufferManager::Shutdown() {
|
||||
base::AutoLock auto_lock(collections_lock_);
|
||||
DCHECK(collections_.empty());
|
||||
allocator_ = nullptr;
|
||||
}
|
||||
|
||||
fuchsia::sysmem::Allocator_Sync* SysmemBufferManager::GetAllocator() {
|
||||
DCHECK(allocator_);
|
||||
return allocator_.get();
|
||||
}
|
||||
|
||||
scoped_refptr<gfx::NativePixmap> SysmemBufferManager::CreateNativePixmap(
|
||||
VkDevice vk_device,
|
||||
gfx::Size size,
|
||||
gfx::BufferFormat format,
|
||||
gfx::BufferUsage usage) {
|
||||
gfx::NativePixmapHandle pixmap_handle;
|
||||
zx::eventpair service_handle;
|
||||
auto status = zx::eventpair::create(
|
||||
0, &pixmap_handle.buffer_collection_handle, &service_handle);
|
||||
ZX_DCHECK(status == ZX_OK, status);
|
||||
|
||||
auto collection = base::MakeRefCounted<SysmemBufferCollection>();
|
||||
if (!collection->Initialize(allocator_.get(), scenic_surface_factory_,
|
||||
std::move(service_handle),
|
||||
/*token_channel=*/zx::channel(), size, format,
|
||||
usage, vk_device, /*min_buffer_count=*/1,
|
||||
/*register_with_image_pipe=*/false)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto result = collection->CreateNativePixmap(std::move(pixmap_handle), size);
|
||||
|
||||
if (result)
|
||||
RegisterCollection(collection);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
scoped_refptr<SysmemBufferCollection>
|
||||
SysmemBufferManager::ImportSysmemBufferCollection(
|
||||
VkDevice vk_device,
|
||||
zx::eventpair service_handle,
|
||||
zx::channel sysmem_token,
|
||||
gfx::Size size,
|
||||
gfx::BufferFormat format,
|
||||
gfx::BufferUsage usage,
|
||||
size_t min_buffer_count,
|
||||
bool register_with_image_pipe) {
|
||||
auto result = base::MakeRefCounted<SysmemBufferCollection>();
|
||||
if (!result->Initialize(allocator_.get(), scenic_surface_factory_,
|
||||
std::move(service_handle), std::move(sysmem_token),
|
||||
size, format, usage, vk_device, min_buffer_count,
|
||||
register_with_image_pipe)) {
|
||||
return nullptr;
|
||||
}
|
||||
RegisterCollection(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void SysmemBufferManager::RegisterCollection(
|
||||
scoped_refptr<SysmemBufferCollection> collection) {
|
||||
{
|
||||
base::AutoLock auto_lock(collections_lock_);
|
||||
DCHECK(!base::Contains(collections_, collection->id()));
|
||||
collections_[collection->id()] = collection;
|
||||
}
|
||||
|
||||
collection->AddOnReleasedCallback(
|
||||
base::BindOnce(&SysmemBufferManager::OnCollectionReleased,
|
||||
base::Unretained(this), collection->id()));
|
||||
}
|
||||
|
||||
scoped_refptr<SysmemBufferCollection>
|
||||
SysmemBufferManager::GetCollectionByHandle(const zx::eventpair& token) {
|
||||
auto koid = base::GetRelatedKoid(token);
|
||||
if (!koid)
|
||||
return nullptr;
|
||||
|
||||
base::AutoLock auto_lock(collections_lock_);
|
||||
auto it = collections_.find(koid.value());
|
||||
return it == collections_.end() ? nullptr : it->second;
|
||||
}
|
||||
|
||||
void SysmemBufferManager::OnCollectionReleased(zx_koid_t id) {
|
||||
base::AutoLock auto_lock(collections_lock_);
|
||||
int erased = collections_.erase(id);
|
||||
DCHECK_EQ(erased, 1);
|
||||
}
|
||||
|
||||
} // namespace ui
|
@ -1,84 +0,0 @@
|
||||
// Copyright 2019 The Chromium Authors
|
||||
// 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_SYSMEM_BUFFER_MANAGER_H_
|
||||
#define UI_OZONE_PLATFORM_SCENIC_SYSMEM_BUFFER_MANAGER_H_
|
||||
|
||||
#include <fuchsia/sysmem/cpp/fidl.h>
|
||||
#include <lib/ui/scenic/cpp/session.h>
|
||||
#include <lib/zx/eventpair.h>
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "base/containers/small_map.h"
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "base/synchronization/lock.h"
|
||||
#include "gpu/vulkan/vulkan_implementation.h"
|
||||
#include "ui/gfx/buffer_types.h"
|
||||
#include "ui/gfx/geometry/size.h"
|
||||
#include "ui/gfx/native_pixmap.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
class SysmemBufferCollection;
|
||||
class ScenicSurfaceFactory;
|
||||
|
||||
class SysmemBufferManager {
|
||||
public:
|
||||
explicit SysmemBufferManager(ScenicSurfaceFactory* scenic_surface_factory);
|
||||
|
||||
SysmemBufferManager(const SysmemBufferManager&) = delete;
|
||||
SysmemBufferManager& operator=(const SysmemBufferManager&) = delete;
|
||||
|
||||
~SysmemBufferManager();
|
||||
|
||||
// Initializes the buffer manager with a connection to the sysmem service.
|
||||
void Initialize(fuchsia::sysmem::AllocatorHandle allocator);
|
||||
|
||||
// Disconnects from the sysmem service. After disconnecting, it's safe to call
|
||||
// Initialize() again.
|
||||
void Shutdown();
|
||||
|
||||
// Returns sysmem allocator. Should only be called after `Initialize()` and
|
||||
// before `Shutdown()`.
|
||||
fuchsia::sysmem::Allocator_Sync* GetAllocator();
|
||||
|
||||
scoped_refptr<gfx::NativePixmap> CreateNativePixmap(VkDevice vk_device,
|
||||
gfx::Size size,
|
||||
gfx::BufferFormat format,
|
||||
gfx::BufferUsage usage);
|
||||
|
||||
scoped_refptr<SysmemBufferCollection> ImportSysmemBufferCollection(
|
||||
VkDevice vk_device,
|
||||
zx::eventpair service_handle,
|
||||
zx::channel sysmem_token,
|
||||
gfx::Size size,
|
||||
gfx::BufferFormat format,
|
||||
gfx::BufferUsage usage,
|
||||
size_t min_buffer_count,
|
||||
bool register_with_image_pipe);
|
||||
|
||||
// Returns `SysmemBufferCollection` that corresnponds to the specified
|
||||
// buffer collection `handle`, which should be the other end of the eventpair
|
||||
// passed to `ImportSysmemBufferCollection()`.
|
||||
scoped_refptr<SysmemBufferCollection> GetCollectionByHandle(
|
||||
const zx::eventpair& handle);
|
||||
|
||||
private:
|
||||
void RegisterCollection(scoped_refptr<SysmemBufferCollection> collection);
|
||||
|
||||
void OnCollectionReleased(zx_koid_t id);
|
||||
|
||||
ScenicSurfaceFactory* const scenic_surface_factory_;
|
||||
fuchsia::sysmem::AllocatorSyncPtr allocator_;
|
||||
|
||||
base::small_map<
|
||||
std::unordered_map<zx_koid_t, scoped_refptr<SysmemBufferCollection>>>
|
||||
collections_ GUARDED_BY(collections_lock_);
|
||||
base::Lock collections_lock_;
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
|
||||
#endif // UI_OZONE_PLATFORM_SCENIC_SYSMEM_BUFFER_MANAGER_H_
|
@ -1,131 +0,0 @@
|
||||
// Copyright 2020 The Chromium Authors
|
||||
// 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/sysmem_native_pixmap.h"
|
||||
|
||||
#include "ui/gfx/gpu_fence.h"
|
||||
#include "ui/gfx/overlay_plane_data.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
namespace {
|
||||
|
||||
zx::event GpuFenceToZxEvent(gfx::GpuFence fence) {
|
||||
DCHECK(!fence.GetGpuFenceHandle().is_null());
|
||||
return fence.GetGpuFenceHandle().Clone().owned_event;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
SysmemNativePixmap::SysmemNativePixmap(
|
||||
scoped_refptr<SysmemBufferCollection> collection,
|
||||
gfx::NativePixmapHandle handle,
|
||||
gfx::Size size)
|
||||
: collection_(collection), handle_(std::move(handle)), size_(size) {}
|
||||
|
||||
SysmemNativePixmap::~SysmemNativePixmap() {
|
||||
if (overlay_image_id_)
|
||||
collection_->scenic_overlay_view()->RemoveImage(overlay_image_id_);
|
||||
}
|
||||
|
||||
bool SysmemNativePixmap::AreDmaBufFdsValid() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
int SysmemNativePixmap::GetDmaBufFd(size_t plane) const {
|
||||
NOTREACHED();
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t SysmemNativePixmap::GetDmaBufPitch(size_t plane) const {
|
||||
NOTREACHED();
|
||||
return 0u;
|
||||
}
|
||||
|
||||
size_t SysmemNativePixmap::GetDmaBufOffset(size_t plane) const {
|
||||
NOTREACHED();
|
||||
return 0u;
|
||||
}
|
||||
|
||||
size_t SysmemNativePixmap::GetDmaBufPlaneSize(size_t plane) const {
|
||||
NOTREACHED();
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t SysmemNativePixmap::GetNumberOfPlanes() const {
|
||||
NOTREACHED();
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool SysmemNativePixmap::SupportsZeroCopyWebGPUImport() const {
|
||||
NOTREACHED();
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t SysmemNativePixmap::GetBufferFormatModifier() const {
|
||||
NOTREACHED();
|
||||
return 0;
|
||||
}
|
||||
|
||||
gfx::BufferFormat SysmemNativePixmap::GetBufferFormat() const {
|
||||
return collection_->format();
|
||||
}
|
||||
|
||||
gfx::Size SysmemNativePixmap::GetBufferSize() const {
|
||||
return size_;
|
||||
}
|
||||
|
||||
uint32_t SysmemNativePixmap::GetUniqueId() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool SysmemNativePixmap::ScheduleOverlayPlane(
|
||||
gfx::AcceleratedWidget widget,
|
||||
const gfx::OverlayPlaneData& overlay_plane_data,
|
||||
std::vector<gfx::GpuFence> acquire_fences,
|
||||
std::vector<gfx::GpuFence> release_fences) {
|
||||
DCHECK(collection_->scenic_overlay_view());
|
||||
ScenicOverlayView* overlay_view = collection_->scenic_overlay_view();
|
||||
|
||||
// Convert gfx::GpuFence to zx::event for PresentImage call.
|
||||
std::vector<zx::event> acquire_events;
|
||||
for (auto& fence : acquire_fences)
|
||||
acquire_events.push_back(GpuFenceToZxEvent(std::move(fence)));
|
||||
std::vector<zx::event> release_events;
|
||||
for (auto& fence : release_fences)
|
||||
release_events.push_back(GpuFenceToZxEvent(std::move(fence)));
|
||||
|
||||
overlay_view->SetBlendMode(overlay_plane_data.enable_blend);
|
||||
|
||||
if (!overlay_image_id_)
|
||||
overlay_image_id_ = overlay_view->AddImage(handle_.buffer_index, size_);
|
||||
|
||||
overlay_view->PresentImage(overlay_image_id_, std::move(acquire_events),
|
||||
std::move(release_events));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
gfx::NativePixmapHandle SysmemNativePixmap::ExportHandle() {
|
||||
return gfx::CloneHandleForIPC(handle_);
|
||||
}
|
||||
|
||||
const gfx::NativePixmapHandle& SysmemNativePixmap::PeekHandle() const {
|
||||
return handle_;
|
||||
}
|
||||
|
||||
bool SysmemNativePixmap::SupportsOverlayPlane() const {
|
||||
// We can display an overlay as long as we have a ScenicOverlayView. Note that
|
||||
// ScenicOverlayView can migrate from one surface to another, but it can't
|
||||
// be used across multiple surfaces similtaneously. But on Fuchsia each buffer
|
||||
// collection is allocated (in FuchsiaVideoDecoder) for a specific web frame,
|
||||
// and each frame can be displayed only on one specific surface.
|
||||
return !!collection_->scenic_overlay_view();
|
||||
}
|
||||
|
||||
ScenicOverlayView* SysmemNativePixmap::GetScenicOverlayView() {
|
||||
return collection_->scenic_overlay_view();
|
||||
}
|
||||
|
||||
} // namespace ui
|
@ -1,67 +0,0 @@
|
||||
// Copyright 2020 The Chromium Authors
|
||||
// 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_SYSMEM_NATIVE_PIXMAP_H_
|
||||
#define UI_OZONE_PLATFORM_SCENIC_SYSMEM_NATIVE_PIXMAP_H_
|
||||
|
||||
#include <lib/zx/eventpair.h>
|
||||
|
||||
#include "ui/gfx/native_pixmap.h"
|
||||
#include "ui/ozone/platform/scenic/sysmem_buffer_collection.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
class ScenicOverlayView;
|
||||
|
||||
class SysmemNativePixmap : public gfx::NativePixmap {
|
||||
public:
|
||||
SysmemNativePixmap(scoped_refptr<SysmemBufferCollection> collection,
|
||||
gfx::NativePixmapHandle handle,
|
||||
gfx::Size size);
|
||||
|
||||
SysmemNativePixmap(const SysmemNativePixmap&) = delete;
|
||||
SysmemNativePixmap& operator=(const SysmemNativePixmap&) = delete;
|
||||
|
||||
// gfx::NativePixmap implementation.
|
||||
bool AreDmaBufFdsValid() const override;
|
||||
int GetDmaBufFd(size_t plane) const override;
|
||||
uint32_t GetDmaBufPitch(size_t plane) const override;
|
||||
size_t GetDmaBufOffset(size_t plane) const override;
|
||||
size_t GetDmaBufPlaneSize(size_t plane) const override;
|
||||
size_t GetNumberOfPlanes() const override;
|
||||
bool SupportsZeroCopyWebGPUImport() const override;
|
||||
uint64_t GetBufferFormatModifier() const override;
|
||||
gfx::BufferFormat GetBufferFormat() const override;
|
||||
gfx::Size GetBufferSize() const override;
|
||||
uint32_t GetUniqueId() const override;
|
||||
bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
|
||||
const gfx::OverlayPlaneData& overlay_plane_data,
|
||||
std::vector<gfx::GpuFence> acquire_fences,
|
||||
std::vector<gfx::GpuFence> release_fences) override;
|
||||
gfx::NativePixmapHandle ExportHandle() override;
|
||||
|
||||
const gfx::NativePixmapHandle& PeekHandle() const;
|
||||
|
||||
// Returns true if overlay planes are supported and ScheduleOverlayPlane() can
|
||||
// be called.
|
||||
bool SupportsOverlayPlane() const;
|
||||
|
||||
// Returns true ScenicOverlayView for the pixmap if any.
|
||||
ScenicOverlayView* GetScenicOverlayView();
|
||||
|
||||
private:
|
||||
~SysmemNativePixmap() override;
|
||||
|
||||
scoped_refptr<SysmemBufferCollection> collection_;
|
||||
gfx::NativePixmapHandle handle_;
|
||||
gfx::Size size_;
|
||||
|
||||
// ID of the image registered with the `ImagePipe` owned by the
|
||||
// `ScenicOverlayView` that corresponds to the `collection_`.
|
||||
uint32_t overlay_image_id_ = 0;
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
|
||||
#endif // UI_OZONE_PLATFORM_SCENIC_SYSMEM_NATIVE_PIXMAP_H_
|
@ -1,256 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// 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/vulkan_implementation_scenic.h"
|
||||
|
||||
#include <lib/ui/scenic/cpp/commands.h>
|
||||
#include <lib/ui/scenic/cpp/session.h>
|
||||
#include <lib/zx/channel.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
|
||||
#include "base/files/file_path.h"
|
||||
#include "gpu/ipc/common/vulkan_ycbcr_info.h"
|
||||
#include "gpu/vulkan/vulkan_function_pointers.h"
|
||||
#include "gpu/vulkan/vulkan_image.h"
|
||||
#include "gpu/vulkan/vulkan_instance.h"
|
||||
#include "gpu/vulkan/vulkan_surface.h"
|
||||
#include "gpu/vulkan/vulkan_util.h"
|
||||
#include "ui/gfx/gpu_fence.h"
|
||||
#include "ui/gfx/gpu_memory_buffer.h"
|
||||
#include "ui/ozone/platform/scenic/scenic_surface.h"
|
||||
#include "ui/ozone/platform/scenic/scenic_surface_factory.h"
|
||||
#include "ui/ozone/platform/scenic/scenic_window.h"
|
||||
#include "ui/ozone/platform/scenic/scenic_window_manager.h"
|
||||
#include "ui/ozone/platform/scenic/sysmem_buffer_collection.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr char kFuchsiaSwapchainLayerName[] =
|
||||
"VK_LAYER_FUCHSIA_imagepipe_swapchain";
|
||||
|
||||
} // namespace
|
||||
|
||||
VulkanImplementationScenic::VulkanImplementationScenic(
|
||||
ScenicSurfaceFactory* scenic_surface_factory,
|
||||
SysmemBufferManager* sysmem_buffer_manager,
|
||||
bool use_swiftshader,
|
||||
bool allow_protected_memory)
|
||||
: VulkanImplementation(use_swiftshader, allow_protected_memory),
|
||||
scenic_surface_factory_(scenic_surface_factory),
|
||||
sysmem_buffer_manager_(sysmem_buffer_manager) {}
|
||||
|
||||
VulkanImplementationScenic::~VulkanImplementationScenic() = default;
|
||||
|
||||
bool VulkanImplementationScenic::InitializeVulkanInstance(bool using_surface) {
|
||||
using_surface_ = using_surface;
|
||||
|
||||
base::FilePath path(use_swiftshader() ? "libvk_swiftshader.so"
|
||||
: "libvulkan.so");
|
||||
vulkan_instance_.BindUnassignedFunctionPointers(path);
|
||||
|
||||
std::vector<const char*> required_extensions;
|
||||
std::vector<const char*> required_layers;
|
||||
|
||||
if (using_surface) {
|
||||
required_extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||
|
||||
// Enable ImagePipe swapchain (not supported in swiftshader).
|
||||
if (!use_swiftshader()) {
|
||||
required_layers.push_back(kFuchsiaSwapchainLayerName);
|
||||
required_extensions.push_back(
|
||||
VK_FUCHSIA_IMAGEPIPE_SURFACE_EXTENSION_NAME);
|
||||
}
|
||||
};
|
||||
|
||||
return vulkan_instance_.InitializeInstance(required_extensions,
|
||||
required_layers);
|
||||
}
|
||||
|
||||
gpu::VulkanInstance* VulkanImplementationScenic::GetVulkanInstance() {
|
||||
return &vulkan_instance_;
|
||||
}
|
||||
|
||||
std::unique_ptr<gpu::VulkanSurface>
|
||||
VulkanImplementationScenic::CreateViewSurface(gfx::AcceleratedWidget window) {
|
||||
DCHECK(using_surface_);
|
||||
|
||||
ScenicSurface* scenic_surface = scenic_surface_factory_->GetSurface(window);
|
||||
fuchsia::images::ImagePipe2Ptr image_pipe;
|
||||
scenic_surface->SetTextureToNewImagePipe(image_pipe.NewRequest());
|
||||
zx_handle_t image_pipe_handle = image_pipe.Unbind().TakeChannel().release();
|
||||
|
||||
VkSurfaceKHR surface;
|
||||
VkImagePipeSurfaceCreateInfoFUCHSIA surface_create_info = {};
|
||||
surface_create_info.sType =
|
||||
VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA;
|
||||
surface_create_info.flags = 0;
|
||||
surface_create_info.imagePipeHandle = image_pipe_handle;
|
||||
|
||||
VkResult result = vkCreateImagePipeSurfaceFUCHSIA(
|
||||
vulkan_instance_.vk_instance(), &surface_create_info, nullptr, &surface);
|
||||
if (result != VK_SUCCESS) {
|
||||
// This shouldn't fail, and we don't know whether imagePipeHandle was closed
|
||||
// if it does.
|
||||
LOG(FATAL) << "vkCreateImagePipeSurfaceFUCHSIA failed: " << result;
|
||||
}
|
||||
|
||||
return std::make_unique<gpu::VulkanSurface>(vulkan_instance_.vk_instance(),
|
||||
window, surface);
|
||||
}
|
||||
|
||||
bool VulkanImplementationScenic::GetPhysicalDevicePresentationSupport(
|
||||
VkPhysicalDevice physical_device,
|
||||
const std::vector<VkQueueFamilyProperties>& queue_family_properties,
|
||||
uint32_t queue_family_index) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<const char*>
|
||||
VulkanImplementationScenic::GetRequiredDeviceExtensions() {
|
||||
std::vector<const char*> result = {
|
||||
VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME,
|
||||
VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME,
|
||||
VK_KHR_BIND_MEMORY_2_EXTENSION_NAME,
|
||||
VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME,
|
||||
VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
|
||||
VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME,
|
||||
VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME,
|
||||
VK_KHR_MAINTENANCE1_EXTENSION_NAME,
|
||||
};
|
||||
|
||||
// Following extensions are not supported by Swiftshader.
|
||||
if (!use_swiftshader()) {
|
||||
result.push_back(VK_FUCHSIA_BUFFER_COLLECTION_EXTENSION_NAME);
|
||||
result.push_back(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME);
|
||||
if (using_surface_)
|
||||
result.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<const char*>
|
||||
VulkanImplementationScenic::GetOptionalDeviceExtensions() {
|
||||
return {};
|
||||
}
|
||||
|
||||
VkFence VulkanImplementationScenic::CreateVkFenceForGpuFence(
|
||||
VkDevice vk_device) {
|
||||
NOTIMPLEMENTED();
|
||||
return VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
std::unique_ptr<gfx::GpuFence>
|
||||
VulkanImplementationScenic::ExportVkFenceToGpuFence(VkDevice vk_device,
|
||||
VkFence vk_fence) {
|
||||
NOTIMPLEMENTED();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
VkExternalMemoryHandleTypeFlagBits
|
||||
VulkanImplementationScenic::GetExternalImageHandleType() {
|
||||
return VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA;
|
||||
}
|
||||
|
||||
VkExternalSemaphoreHandleTypeFlagBits
|
||||
VulkanImplementationScenic::GetExternalSemaphoreHandleType() {
|
||||
return VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA;
|
||||
}
|
||||
|
||||
bool VulkanImplementationScenic::CanImportGpuMemoryBuffer(
|
||||
gpu::VulkanDeviceQueue* device_queue,
|
||||
gfx::GpuMemoryBufferType memory_buffer_type) {
|
||||
return memory_buffer_type == gfx::NATIVE_PIXMAP;
|
||||
}
|
||||
|
||||
std::unique_ptr<gpu::VulkanImage>
|
||||
VulkanImplementationScenic::CreateImageFromGpuMemoryHandle(
|
||||
gpu::VulkanDeviceQueue* device_queue,
|
||||
gfx::GpuMemoryBufferHandle gmb_handle,
|
||||
gfx::Size size,
|
||||
VkFormat vk_format,
|
||||
const gfx::ColorSpace& color_space) {
|
||||
if (gmb_handle.type != gfx::NATIVE_PIXMAP)
|
||||
return nullptr;
|
||||
|
||||
if (!gmb_handle.native_pixmap_handle.buffer_collection_handle) {
|
||||
DLOG(ERROR) << "NativePixmapHandle.buffer_collection_handle is not set.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto collection = sysmem_buffer_manager_->GetCollectionByHandle(
|
||||
gmb_handle.native_pixmap_handle.buffer_collection_handle);
|
||||
if (!collection) {
|
||||
DLOG(ERROR) << "Tried to use an unknown buffer collection ID.";
|
||||
return nullptr;
|
||||
}
|
||||
VkImage vk_image = VK_NULL_HANDLE;
|
||||
VkImageCreateInfo vk_image_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
|
||||
VkDeviceMemory vk_device_memory = VK_NULL_HANDLE;
|
||||
VkDeviceSize vk_device_size = 0;
|
||||
if (!collection->CreateVkImage(gmb_handle.native_pixmap_handle.buffer_index,
|
||||
device_queue->GetVulkanDevice(), size,
|
||||
&vk_image, &vk_image_info, &vk_device_memory,
|
||||
&vk_device_size)) {
|
||||
DLOG(ERROR) << "CreateVkImage failed.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
absl::optional<gpu::VulkanYCbCrInfo> ycbcr_info;
|
||||
if (collection->format() == gfx::BufferFormat::YUV_420_BIPLANAR) {
|
||||
VkSamplerYcbcrModelConversion ycbcr_conversion =
|
||||
(color_space.GetMatrixID() == gfx::ColorSpace::MatrixID::BT709)
|
||||
? VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709
|
||||
: VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601;
|
||||
|
||||
// Currently sysmem doesn't specify location of chroma samples relative to
|
||||
// luma (see fxbug.dev/13677). Assume they are cosited with luma. Y'CbCr
|
||||
// info here must match the values passed for the same buffer in
|
||||
// FuchsiaVideoDecoder. |format_features| are resolved later in the GPU
|
||||
// process before the ycbcr info is passed to Skia.
|
||||
ycbcr_info = gpu::VulkanYCbCrInfo(
|
||||
vk_image_info.format, /*external_format=*/0, ycbcr_conversion,
|
||||
VK_SAMPLER_YCBCR_RANGE_ITU_NARROW, VK_CHROMA_LOCATION_COSITED_EVEN,
|
||||
VK_CHROMA_LOCATION_COSITED_EVEN, /*format_features=*/0);
|
||||
}
|
||||
|
||||
auto image = gpu::VulkanImage::Create(
|
||||
device_queue, vk_image, vk_device_memory, size, vk_image_info.format,
|
||||
vk_image_info.tiling, vk_device_size, 0 /* memory_type_index */,
|
||||
ycbcr_info, vk_image_info.usage, vk_image_info.flags);
|
||||
|
||||
if (image->format() != vk_format) {
|
||||
DLOG(ERROR) << "Unexpected format " << vk_format << " vs "
|
||||
<< image->format();
|
||||
image->Destroy();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
image->set_queue_family_index(VK_QUEUE_FAMILY_EXTERNAL);
|
||||
image->set_native_pixmap(collection->CreateNativePixmap(
|
||||
std::move(gmb_handle.native_pixmap_handle), size));
|
||||
return image;
|
||||
}
|
||||
|
||||
void VulkanImplementationScenic::RegisterSysmemBufferCollection(
|
||||
VkDevice device,
|
||||
zx::eventpair service_handle,
|
||||
zx::channel sysmem_token,
|
||||
gfx::BufferFormat format,
|
||||
gfx::BufferUsage usage,
|
||||
gfx::Size size,
|
||||
size_t min_buffer_count,
|
||||
bool register_with_image_pipe) {
|
||||
fuchsia::images::ImagePipe2Ptr image_pipe = nullptr;
|
||||
sysmem_buffer_manager_->ImportSysmemBufferCollection(
|
||||
device, std::move(service_handle), std::move(sysmem_token), size, format,
|
||||
usage, min_buffer_count, register_with_image_pipe);
|
||||
}
|
||||
|
||||
} // namespace ui
|
@ -1,79 +0,0 @@
|
||||
// Copyright 2018 The Chromium Authors
|
||||
// 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_VULKAN_IMPLEMENTATION_SCENIC_H_
|
||||
#define UI_OZONE_PLATFORM_SCENIC_VULKAN_IMPLEMENTATION_SCENIC_H_
|
||||
|
||||
#include <fuchsia/ui/scenic/cpp/fidl.h>
|
||||
#include <memory>
|
||||
|
||||
#include "gpu/vulkan/vulkan_implementation.h"
|
||||
#include "gpu/vulkan/vulkan_instance.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
class ScenicSurfaceFactory;
|
||||
class SysmemBufferManager;
|
||||
|
||||
class VulkanImplementationScenic : public gpu::VulkanImplementation {
|
||||
public:
|
||||
VulkanImplementationScenic(ScenicSurfaceFactory* scenic_surface_factory,
|
||||
SysmemBufferManager* sysmem_buffer_manager,
|
||||
bool use_swiftshader,
|
||||
bool allow_protected_memory);
|
||||
|
||||
VulkanImplementationScenic(const VulkanImplementationScenic&) = delete;
|
||||
VulkanImplementationScenic& operator=(const VulkanImplementationScenic&) =
|
||||
delete;
|
||||
|
||||
~VulkanImplementationScenic() override;
|
||||
|
||||
// VulkanImplementation:
|
||||
bool InitializeVulkanInstance(bool using_surface) override;
|
||||
gpu::VulkanInstance* GetVulkanInstance() override;
|
||||
std::unique_ptr<gpu::VulkanSurface> CreateViewSurface(
|
||||
gfx::AcceleratedWidget window) override;
|
||||
bool GetPhysicalDevicePresentationSupport(
|
||||
VkPhysicalDevice device,
|
||||
const std::vector<VkQueueFamilyProperties>& queue_family_properties,
|
||||
uint32_t queue_family_index) override;
|
||||
std::vector<const char*> GetRequiredDeviceExtensions() override;
|
||||
std::vector<const char*> GetOptionalDeviceExtensions() override;
|
||||
VkFence CreateVkFenceForGpuFence(VkDevice vk_device) override;
|
||||
std::unique_ptr<gfx::GpuFence> ExportVkFenceToGpuFence(
|
||||
VkDevice vk_device,
|
||||
VkFence vk_fence) override;
|
||||
VkExternalMemoryHandleTypeFlagBits GetExternalImageHandleType() override;
|
||||
VkExternalSemaphoreHandleTypeFlagBits GetExternalSemaphoreHandleType()
|
||||
override;
|
||||
bool CanImportGpuMemoryBuffer(
|
||||
gpu::VulkanDeviceQueue* device_queue,
|
||||
gfx::GpuMemoryBufferType memory_buffer_type) override;
|
||||
std::unique_ptr<gpu::VulkanImage> CreateImageFromGpuMemoryHandle(
|
||||
gpu::VulkanDeviceQueue* device_queue,
|
||||
gfx::GpuMemoryBufferHandle gmb_handle,
|
||||
gfx::Size size,
|
||||
VkFormat vk_format,
|
||||
const gfx::ColorSpace& color_space) override;
|
||||
void RegisterSysmemBufferCollection(VkDevice device,
|
||||
zx::eventpair service_handle,
|
||||
zx::channel sysmem_token,
|
||||
gfx::BufferFormat format,
|
||||
gfx::BufferUsage usage,
|
||||
gfx::Size size,
|
||||
size_t min_buffer_count,
|
||||
bool register_with_image_pipe) override;
|
||||
|
||||
private:
|
||||
ScenicSurfaceFactory* const scenic_surface_factory_;
|
||||
SysmemBufferManager* const sysmem_buffer_manager_;
|
||||
|
||||
gpu::VulkanInstance vulkan_instance_;
|
||||
|
||||
bool using_surface_ = false;
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
|
||||
#endif // UI_OZONE_PLATFORM_SCENIC_VULKAN_IMPLEMENTATION_SCENIC_H_
|
@ -32,6 +32,8 @@ component("platform_window") {
|
||||
"fuchsia/initialize_presenter_api_view.cc",
|
||||
"fuchsia/initialize_presenter_api_view.h",
|
||||
"fuchsia/scenic_window_delegate.h",
|
||||
"fuchsia/view_ref_pair.cc",
|
||||
"fuchsia/view_ref_pair.h",
|
||||
]
|
||||
|
||||
public_deps += [
|
||||
|
@ -5,8 +5,6 @@
|
||||
#include "ui/platform_window/fuchsia/initialize_presenter_api_view.h"
|
||||
|
||||
#include <lib/sys/cpp/component_context.h>
|
||||
#include <lib/ui/scenic/cpp/view_ref_pair.h>
|
||||
#include <lib/ui/scenic/cpp/view_token_pair.h>
|
||||
#include <zircon/rights.h>
|
||||
|
||||
#include <utility>
|
||||
|
21
ui/platform_window/fuchsia/view_ref_pair.cc
Normal file
21
ui/platform_window/fuchsia/view_ref_pair.cc
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright 2023 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "ui/platform_window/fuchsia/view_ref_pair.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
ViewRefPair ViewRefPair::New() {
|
||||
ViewRefPair ref_pair;
|
||||
zx::eventpair::create(/*options*/ 0u, &ref_pair.control_ref.reference,
|
||||
&ref_pair.view_ref.reference);
|
||||
ref_pair.control_ref.reference.replace(
|
||||
ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE),
|
||||
&ref_pair.control_ref.reference);
|
||||
ref_pair.view_ref.reference.replace(ZX_RIGHTS_BASIC,
|
||||
&ref_pair.view_ref.reference);
|
||||
return ref_pair;
|
||||
}
|
||||
|
||||
} // namespace ui
|
27
ui/platform_window/fuchsia/view_ref_pair.h
Normal file
27
ui/platform_window/fuchsia/view_ref_pair.h
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright 2023 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef UI_PLATFORM_WINDOW_FUCHSIA_VIEW_REF_PAIR_H_
|
||||
#define UI_PLATFORM_WINDOW_FUCHSIA_VIEW_REF_PAIR_H_
|
||||
|
||||
#include <fuchsia/ui/views/cpp/fidl.h>
|
||||
#include <lib/zx/eventpair.h>
|
||||
#include <utility>
|
||||
|
||||
#include "base/component_export.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
struct COMPONENT_EXPORT(PLATFORM_WINDOW) ViewRefPair {
|
||||
// ViewRef creation for the legacy graphics API. For Flatland, use
|
||||
// scenic::NewViewIdentityOnCreation().
|
||||
static ViewRefPair New();
|
||||
|
||||
fuchsia::ui::views::ViewRefControl control_ref;
|
||||
fuchsia::ui::views::ViewRef view_ref;
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
|
||||
#endif // UI_PLATFORM_WINDOW_FUCHSIA_VIEW_REF_PAIR_H_
|
@ -20,7 +20,7 @@
|
||||
#include <fuchsia/element/cpp/fidl.h>
|
||||
#include <fuchsia/ui/composition/cpp/fidl.h>
|
||||
#include <fuchsia/ui/views/cpp/fidl.h>
|
||||
#include <lib/ui/scenic/cpp/view_ref_pair.h>
|
||||
#include <ui/platform_window/fuchsia/view_ref_pair.h>
|
||||
#endif
|
||||
|
||||
namespace gfx {
|
||||
@ -91,7 +91,7 @@ struct COMPONENT_EXPORT(PLATFORM_WINDOW) PlatformWindowInitProperties {
|
||||
fuchsia::ui::views::ViewToken view_token;
|
||||
fuchsia::ui::views::ViewCreationToken view_creation_token;
|
||||
|
||||
scenic::ViewRefPair view_ref_pair;
|
||||
ViewRefPair view_ref_pair;
|
||||
|
||||
// Used to coordinate window closure requests with the shell.
|
||||
fuchsia::element::ViewControllerPtr view_controller;
|
||||
|
Reference in New Issue
Block a user