Commit b81d0e7f authored by Maksim Sisov's avatar Maksim Sisov Committed by Commit Bot

[ozone/wayland] Add initial display fetch support for Wayland.

This cl adds an initial display fetching support for Ozone/Wayland:
  - First, DesktopScreenOzone adds itself as an observer to a
    NativeDisplayDelegate, which has its own implementation based on
    a platform.
  - Then, DesktopScreenOzone initializes NativeDisplayDelegate and,
    in case of WaylandNativeDisplayDelegate, WaylandNativeDisplayDelegate
    sets itself as an observer to a PrimaryOutput.
  - Once PrimaryOutput creates current display's snapshot and current mode
    , (WaylandNativeDisplayDelegate::)OnOutputReadyForUse is called,
    WaylandNativeDisplayDelegate notifies its observers (DesktopScreenOzone
    in this case) through OnConfigurationChanged method.
  - Then, DesktopScreenOzone calls NativeDisplayDelegate::GetDisplays,
    which returns a vector of display snapshots through a callback, and
    DesktopScreenOzone::OnHostDisplaysReady creates a display::Display
    with parameters it gets from display::DisplaySnapshot.

Preliminary support for mode changes has also been added. If we take a
normal run-time browser flow, WaylandOutput::OutputHandleMode can be
called on every display change (it can be a resolution change, a refresh rate
change and etc). Once |current_mode_| is updated, OnOutputReadyForUse is
again called and DesktopScreenOzone fetches the newest list of displays,
which is then used to create a display::Display with the ids provided.
As a result, ProcessDisplayChanged is called and stored display::Display
updated by checking its id.

Note: it's impossible to run Wayland without --in-process-gpu flag
as long as support for gpu process communication with wayland
connection is not in place yet, but it's under development and
going to be pushed soon.

To try this, compile with the following gn args
use_ozone = true
ozone_platform_wayland = true

TEST=./out/Debug/chrome --ozone-platform=wayland --in-process-gpu

Bug: 578890
Change-Id: Ia0f61f1af24eeb46433d22cf31f69396325e4c78
Reviewed-on: https://chromium-review.googlesource.com/1051829Reviewed-by: default avatarRobert Kroeger <rjkroege@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Commit-Queue: Maksim Sisov <msisov@igalia.com>
Cr-Commit-Position: refs/heads/master@{#559446}
parent 3792ea13
......@@ -32,6 +32,8 @@ source_set("wayland") {
"wayland_data_source.h",
"wayland_keyboard.cc",
"wayland_keyboard.h",
"wayland_native_display_delegate.cc",
"wayland_native_display_delegate.h",
"wayland_object.cc",
"wayland_object.h",
"wayland_output.cc",
......
......@@ -11,6 +11,7 @@
#include "ui/events/system_input_injector.h"
#include "ui/ozone/common/stub_overlay_manager.h"
#include "ui/ozone/platform/wayland/wayland_connection.h"
#include "ui/ozone/platform/wayland/wayland_native_display_delegate.h"
#include "ui/ozone/platform/wayland/wayland_surface_factory.h"
#include "ui/ozone/platform/wayland/wayland_window.h"
#include "ui/ozone/public/gpu_platform_support_host.h"
......@@ -70,7 +71,7 @@ class OzonePlatformWayland : public OzonePlatform {
std::unique_ptr<display::NativeDisplayDelegate> CreateNativeDisplayDelegate()
override {
return std::make_unique<display::FakeDisplayDelegate>();
return std::make_unique<WaylandNativeDisplayDelegate>(connection_.get());
}
void InitializeUI(const InitParams& args) override {
......
......@@ -49,7 +49,9 @@ bool WaylandConnection::Initialize() {
}
wl_registry_add_listener(registry_.get(), &registry_listener, this);
wl_display_roundtrip(display_.get());
while (!PrimaryOutput() || !PrimaryOutput()->is_ready())
wl_display_roundtrip(display_.get());
if (!compositor_) {
LOG(ERROR) << "No wl_compositor object";
......@@ -299,8 +301,8 @@ void WaylandConnection::Global(void* data,
if (!connection->output_list_.empty())
NOTIMPLEMENTED() << "Multiple screens support is not implemented";
connection->output_list_.push_back(
base::WrapUnique(new WaylandOutput(output.release())));
connection->output_list_.push_back(base::WrapUnique(new WaylandOutput(
connection->get_next_display_id(), output.release())));
} else if (!connection->data_device_manager_ &&
strcmp(interface, "wl_data_device_manager") == 0) {
wl::Object<wl_data_device_manager> data_device_manager =
......
......@@ -49,6 +49,7 @@ class WaylandConnection : public PlatformEventSource,
void AddWindow(gfx::AcceleratedWidget widget, WaylandWindow* window);
void RemoveWindow(gfx::AcceleratedWidget widget);
int64_t get_next_display_id() { return next_display_id_++; }
const std::vector<std::unique_ptr<WaylandOutput>>& GetOutputList() const;
WaylandOutput* PrimaryOutput() const;
......@@ -133,6 +134,7 @@ class WaylandConnection : public PlatformEventSource,
uint32_t serial_ = 0;
int64_t next_display_id_ = 0;
std::vector<std::unique_ptr<WaylandOutput>> output_list_;
// Holds a temporary instance of the client's clipboard content
......
......@@ -8,6 +8,7 @@
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/display/types/display_snapshot.h"
#include "ui/ozone/platform/wayland/fake_server.h"
#include "ui/ozone/platform/wayland/wayland_connection.h"
#include "ui/ozone/platform/wayland/wayland_output.h"
......@@ -15,7 +16,20 @@
namespace ui {
namespace {
const uint32_t kXdgVersion5 = 5;
const uint32_t kNumOfDisplays = 1;
const uint32_t kWidth = 800;
const uint32_t kHeight = 600;
void CheckDisplaySize(const std::vector<display::DisplaySnapshot*>& displays) {
ASSERT_TRUE(displays.size() == kNumOfDisplays);
// TODO(msisov): add multiple displays support.
display::DisplaySnapshot* display_snapshot = displays.front();
ASSERT_TRUE(display_snapshot->current_mode()->size() ==
gfx::Size(kWidth, kHeight));
}
}
class OutputObserver : public WaylandOutput::Observer {
......@@ -68,7 +82,7 @@ TEST(WaylandConnectionTest, Output) {
base::MessageLoopForUI message_loop;
wl::FakeServer server;
ASSERT_TRUE(server.Start(kXdgVersion5));
server.output()->SetRect(gfx::Rect(0, 0, 800, 600));
server.output()->SetRect(gfx::Rect(0, 0, kWidth, kHeight));
WaylandConnection connection;
ASSERT_TRUE(connection.Initialize());
connection.StartProcessingEvents();
......@@ -78,10 +92,8 @@ TEST(WaylandConnectionTest, Output) {
connection.PrimaryOutput()->SetObserver(&observer);
run_loop.Run();
ASSERT_TRUE(connection.GetOutputList().size() == 1);
WaylandOutput* output = connection.PrimaryOutput();
ASSERT_TRUE(output->Geometry().width() == 800);
ASSERT_TRUE(output->Geometry().height() == 600);
connection.PrimaryOutput()->GetDisplaysSnapshot(
base::BindOnce(&CheckDisplaySize));
server.Resume();
base::RunLoop().RunUntilIdle();
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/ozone/platform/wayland/wayland_native_display_delegate.h"
#include "ui/display/types/display_snapshot.h"
#include "ui/display/types/native_display_observer.h"
#include "ui/ozone/platform/wayland/wayland_connection.h"
namespace ui {
WaylandNativeDisplayDelegate::WaylandNativeDisplayDelegate(
WaylandConnection* connection)
: connection_(connection) {}
WaylandNativeDisplayDelegate::~WaylandNativeDisplayDelegate() {
connection_->PrimaryOutput()->SetObserver(nullptr);
}
void WaylandNativeDisplayDelegate::Initialize() {
// TODO(msisov): Add support for secondary output.
WaylandOutput* primary_output = connection_->PrimaryOutput();
if (!primary_output)
NOTREACHED() << "Asynchronous display data fetching is not available";
primary_output->SetObserver(this);
}
void WaylandNativeDisplayDelegate::TakeDisplayControl(
display::DisplayControlCallback callback) {
NOTREACHED();
}
void WaylandNativeDisplayDelegate::RelinquishDisplayControl(
display::DisplayControlCallback callback) {
NOTREACHED();
}
void WaylandNativeDisplayDelegate::GetDisplays(
display::GetDisplaysCallback callback) {
if (displays_ready_)
connection_->PrimaryOutput()->GetDisplaysSnapshot(std::move(callback));
}
void WaylandNativeDisplayDelegate::Configure(
const display::DisplaySnapshot& output,
const display::DisplayMode* mode,
const gfx::Point& origin,
display::ConfigureCallback callback) {
NOTREACHED();
}
void WaylandNativeDisplayDelegate::GetHDCPState(
const display::DisplaySnapshot& output,
display::GetHDCPStateCallback callback) {
NOTREACHED();
}
void WaylandNativeDisplayDelegate::SetHDCPState(
const display::DisplaySnapshot& output,
display::HDCPState state,
display::SetHDCPStateCallback callback) {
NOTREACHED();
}
bool WaylandNativeDisplayDelegate::SetColorCorrection(
const display::DisplaySnapshot& output,
const std::vector<display::GammaRampRGBEntry>& degamma_lut,
const std::vector<display::GammaRampRGBEntry>& gamma_lut,
const std::vector<float>& correction_matrix) {
NOTREACHED();
return false;
}
void WaylandNativeDisplayDelegate::AddObserver(
display::NativeDisplayObserver* observer) {
observers_.AddObserver(observer);
}
void WaylandNativeDisplayDelegate::RemoveObserver(
display::NativeDisplayObserver* observer) {
observers_.RemoveObserver(observer);
}
display::FakeDisplayController*
WaylandNativeDisplayDelegate::GetFakeDisplayController() {
return nullptr;
}
void WaylandNativeDisplayDelegate::OnOutputReadyForUse() {
if (!displays_ready_)
displays_ready_ = true;
for (display::NativeDisplayObserver& observer : observers_)
observer.OnConfigurationChanged();
}
} // namespace ui
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_OZONE_PLATFORM_WAYLAND_WAYLAND_NATIVE_DISPLAY_DELEGATE_H_
#define UI_OZONE_PLATFORM_WAYLAND_WAYLAND_NATIVE_DISPLAY_DELEGATE_H_
#include <stdint.h>
#include "base/macros.h"
#include "base/observer_list.h"
#include "ui/display/types/native_display_delegate.h"
#include "ui/ozone/platform/wayland/wayland_output.h"
namespace ui {
class WaylandConnection;
class WaylandNativeDisplayDelegate : public display::NativeDisplayDelegate,
public WaylandOutput::Observer {
public:
explicit WaylandNativeDisplayDelegate(WaylandConnection* connection);
~WaylandNativeDisplayDelegate() override;
// display::NativeDisplayDelegate overrides:
void Initialize() override;
void TakeDisplayControl(display::DisplayControlCallback callback) override;
void RelinquishDisplayControl(
display::DisplayControlCallback callback) override;
void GetDisplays(display::GetDisplaysCallback callback) override;
void Configure(const display::DisplaySnapshot& output,
const display::DisplayMode* mode,
const gfx::Point& origin,
display::ConfigureCallback callback) override;
void GetHDCPState(const display::DisplaySnapshot& output,
display::GetHDCPStateCallback callback) override;
void SetHDCPState(const display::DisplaySnapshot& output,
display::HDCPState state,
display::SetHDCPStateCallback callback) override;
bool SetColorCorrection(
const display::DisplaySnapshot& output,
const std::vector<display::GammaRampRGBEntry>& degamma_lut,
const std::vector<display::GammaRampRGBEntry>& gamma_lut,
const std::vector<float>& correction_matrix) override;
void AddObserver(display::NativeDisplayObserver* observer) override;
void RemoveObserver(display::NativeDisplayObserver* observer) override;
display::FakeDisplayController* GetFakeDisplayController() override;
// WaylandOutput::Observer overrides:
void OnOutputReadyForUse() override;
private:
WaylandConnection* connection_; // Not owned.
base::ObserverList<display::NativeDisplayObserver> observers_;
bool displays_ready_ = false;
DISALLOW_COPY_AND_ASSIGN(WaylandNativeDisplayDelegate);
};
} // namespace ui
#endif // UI_OZONE_PLATFORM_WAYLAND_WAYLAND_NATIVE_DISPLAY_DELEGATE_H_
......@@ -6,12 +6,13 @@
#include <wayland-client.h>
#include "ui/gfx/color_space.h"
#include "ui/ozone/platform/wayland/wayland_connection.h"
namespace ui {
WaylandOutput::WaylandOutput(wl_output* output)
: output_(output), rect_(0, 0, 0, 0), observer_(nullptr) {
WaylandOutput::WaylandOutput(const int64_t display_id, wl_output* output)
: display_id_(display_id), output_(output), observer_(nullptr) {
static const wl_output_listener output_listener = {
&WaylandOutput::OutputHandleGeometry, &WaylandOutput::OutputHandleMode,
};
......@@ -20,6 +21,18 @@ WaylandOutput::WaylandOutput(wl_output* output)
WaylandOutput::~WaylandOutput() {}
void WaylandOutput::SetObserver(Observer* observer) {
observer_ = observer;
if (current_mode_)
observer_->OnOutputReadyForUse();
}
void WaylandOutput::GetDisplaysSnapshot(display::GetDisplaysCallback callback) {
std::vector<display::DisplaySnapshot*> snapshot;
snapshot.push_back(current_snapshot_.get());
std::move(callback).Run(snapshot);
}
// static
void WaylandOutput::OutputHandleGeometry(void* data,
wl_output* output,
......@@ -32,7 +45,13 @@ void WaylandOutput::OutputHandleGeometry(void* data,
const char* model,
int32_t output_transform) {
WaylandOutput* wayland_output = static_cast<WaylandOutput*>(data);
wayland_output->rect_.set_origin(gfx::Point(x, y));
wayland_output->current_snapshot_.reset(new display::DisplaySnapshot(
wayland_output->display_id_, gfx::Point(x, y),
gfx::Size(physical_width, physical_height),
display::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_NONE, false,
false, false, gfx::ColorSpace(), model, base::FilePath(),
display::DisplaySnapshot::DisplayModeList(), std::vector<uint8_t>(),
nullptr, nullptr, 0, 0, gfx::Size()));
}
// static
......@@ -45,8 +64,11 @@ void WaylandOutput::OutputHandleMode(void* data,
WaylandOutput* output = static_cast<WaylandOutput*>(data);
if (flags & WL_OUTPUT_MODE_CURRENT) {
output->rect_.set_width(width);
output->rect_.set_height(height);
std::unique_ptr<display::DisplayMode> previous_mode =
std::move(output->current_mode_);
output->current_mode_.reset(
new display::DisplayMode(gfx::Size(width, height), false, refresh));
output->current_snapshot_->set_current_mode(output->current_mode_.get());
if (output->observer())
output->observer()->OnOutputReadyForUse();
......
......@@ -7,6 +7,8 @@
#include <stdint.h>
#include "ui/display/types/display_snapshot.h"
#include "ui/display/types/native_display_delegate.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/ozone/platform/wayland/wayland_object.h"
......@@ -22,14 +24,16 @@ class WaylandOutput {
virtual void OnOutputReadyForUse() = 0;
};
WaylandOutput(wl_output*);
WaylandOutput(const int64_t display_id, wl_output* output);
~WaylandOutput();
// Returns the geometry of the output.
gfx::Rect Geometry() const { return rect_; }
void SetObserver(Observer* observer) { observer_ = observer; }
void SetObserver(Observer* observer);
Observer* observer() { return observer_; }
bool is_ready() const { return !!current_mode_; }
void GetDisplaysSnapshot(display::GetDisplaysCallback callback);
private:
// Callback functions used for setting geometric properties of the output
// and available modes.
......@@ -51,11 +55,14 @@ class WaylandOutput {
int32_t height,
int32_t refresh);
const int64_t display_id_ = 0;
wl::Object<wl_output> output_;
gfx::Rect rect_;
Observer* observer_;
std::unique_ptr<display::DisplaySnapshot> current_snapshot_;
std::unique_ptr<display::DisplayMode> current_mode_;
DISALLOW_COPY_AND_ASSIGN(WaylandOutput);
};
......
......@@ -4,32 +4,53 @@
#include "ui/views/widget/desktop_aura/desktop_screen_ozone.h"
#include "ui/display/display.h"
#include "ui/display/types/display_constants.h"
#include "ui/display/types/display_snapshot.h"
#include "ui/display/types/native_display_delegate.h"
#include "ui/gfx/geometry/dip_util.h"
#include "ui/ozone/public/ozone_platform.h"
#include "ui/views/widget/desktop_aura/desktop_screen.h"
namespace views {
DesktopScreenOzone::DesktopScreenOzone() {
// TODO(msisov): Turn this hack into a real fetching of displays snapshot,
// which will be used to create a real display::Display based on the
// information from snapshots.
DesktopScreenOzone::DesktopScreenOzone()
: delegate_(
ui::OzonePlatform::GetInstance()->CreateNativeDisplayDelegate()) {
delegate_->AddObserver(this);
delegate_->Initialize();
}
DesktopScreenOzone::~DesktopScreenOzone() = default;
void DesktopScreenOzone::OnHostDisplaysReady(
const std::vector<display::DisplaySnapshot*>& displays) {
DCHECK(!displays.empty());
// TODO(msisov): Add support for multiple displays.
display::DisplaySnapshot* display_snapshot = displays.front();
DCHECK(display_snapshot);
float device_scale_factor = 1.f;
if (display::Display::HasForceDeviceScaleFactor())
device_scale_factor = display::Display::GetForcedDeviceScaleFactor();
gfx::Size scaled_size =
gfx::ConvertSizeToDIP(device_scale_factor, gfx::Size(800, 600));
gfx::Size scaled_size = gfx::ConvertSizeToDIP(
device_scale_factor, display_snapshot->current_mode()->size());
const int64_t display_id = 1;
display::Display display(display_id);
display::Display display(display_snapshot->display_id());
display.set_bounds(gfx::Rect(scaled_size));
display.set_work_area(gfx::Rect(0, 0, 800, 600));
display.set_work_area(display.bounds());
display.set_device_scale_factor(device_scale_factor);
ProcessDisplayChanged(display, true /* is_primary */);
}
DesktopScreenOzone::~DesktopScreenOzone() = default;
void DesktopScreenOzone::OnConfigurationChanged() {
delegate_->GetDisplays(base::BindOnce(
&DesktopScreenOzone::OnHostDisplaysReady, base::Unretained(this)));
}
void DesktopScreenOzone::OnDisplaySnapshotsInvalidated() {}
//////////////////////////////////////////////////////////////////////////////
......
......@@ -6,15 +6,31 @@
#define UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_SCREEN_OZONE_H_
#include "ui/display/screen_base.h"
#include "ui/display/types/native_display_observer.h"
namespace display {
class NativeDisplayDelegate;
class DisplaySnapshot;
} // namespace display
namespace views {
class DesktopScreenOzone : public display::ScreenBase {
class DesktopScreenOzone : public display::ScreenBase,
public display::NativeDisplayObserver {
public:
DesktopScreenOzone();
~DesktopScreenOzone() override;
private:
void OnHostDisplaysReady(
const std::vector<display::DisplaySnapshot*>& displays);
// display::NativeDisplayDelegate:
void OnConfigurationChanged() override;
void OnDisplaySnapshotsInvalidated() override;
std::unique_ptr<display::NativeDisplayDelegate> delegate_;
DISALLOW_COPY_AND_ASSIGN(DesktopScreenOzone);
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment