[XProto] Ensure x11::Connection is only used on a single thread
This fixes bug 1109422 which is caused by using the same x11::Connection from both the GPU main thread and the viz compositor thread. Summary of changes: * x11::Connection is now stored in TLS instead of as a singleton. This does not affect the browser process, but it means the GPU process will now have 2 connections: 1 for the main thread and 1 for the viz compositor thread. Additionally, chrome will have 3 connections when running in single-process-mode. * In X11 and Ozone/X11 contexts, the viz compositor thread must be a UI thread now so it can dispatch X events. This required making MessagePumpGlib compatible with multiple threads. * The GPU sandbox presents a challenge: we cannot open an X11 connection once it's up, since the socket() and connect() syscalls are blocked. To workaround this, we must open the viz compositor X11 connection the same time we open the main thread's X11 connection. For now, we stuff it in ui::X11UiThread as an obnoxious global variable. XShmImagePool and X11SoftwareBitmapPresenter are simplified as they are now only used on one thread. Also CreateVizCompositorThread() no longer requires a TaskRunner argument. With this change, once we remove the rest of Xlib, we can remove any locking when using X11. BUG=1066670,1078392,1109422 R=nickdiego,sky,msisov,rjkroege Change-Id: If122c071a2eef38ba0469fe592ab9cc71ccf6011 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2343314 Auto-Submit: Thomas Anderson <thomasanderson@chromium.org> Reviewed-by: Sadrul Chowdhury <sadrul@chromium.org> Reviewed-by: Zhenyao Mo <zmo@chromium.org> Reviewed-by: Robert Kroeger <rjkroege@chromium.org> Reviewed-by: Maksim Sisov (GMT+3) <msisov@igalia.com> Reviewed-by: Nick Yamane <nickdiego@igalia.com> Reviewed-by: kylechar <kylechar@chromium.org> Commit-Queue: Thomas Anderson <thomasanderson@chromium.org> Cr-Commit-Position: refs/heads/master@{#799697}
This commit is contained in:
base/message_loop
components/viz/service
display_embedder
main
content/gpu
ui
base
x
events
devices
platform
gfx
ozone
demo
platform
cast
drm
headless
scenic
wayland
x11
public
@@ -5,16 +5,13 @@
|
|||||||
#include "base/message_loop/message_pump_glib.h"
|
#include "base/message_loop/message_pump_glib.h"
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <glib.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include <glib.h>
|
|
||||||
|
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
#include "base/no_destructor.h"
|
|
||||||
#include "base/numerics/safe_conversions.h"
|
#include "base/numerics/safe_conversions.h"
|
||||||
#include "base/posix/eintr_wrapper.h"
|
#include "base/posix/eintr_wrapper.h"
|
||||||
#include "base/synchronization/lock.h"
|
#include "base/synchronization/lock.h"
|
||||||
#include "base/threading/platform_thread.h"
|
|
||||||
|
|
||||||
namespace base {
|
namespace base {
|
||||||
|
|
||||||
@@ -50,6 +47,12 @@ int GetTimeIntervalMilliseconds(TimeTicks next_task_time) {
|
|||||||
return timeout_ms < 0 ? 0 : saturated_cast<int>(timeout_ms);
|
return timeout_ms < 0 ? 0 : saturated_cast<int>(timeout_ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RunningOnMainThread() {
|
||||||
|
auto pid = getpid();
|
||||||
|
auto tid = PlatformThread::CurrentId();
|
||||||
|
return pid > 0 && tid > 0 && pid == tid;
|
||||||
|
}
|
||||||
|
|
||||||
// A brief refresher on GLib:
|
// A brief refresher on GLib:
|
||||||
// GLib sources have four callbacks: Prepare, Check, Dispatch and Finalize.
|
// GLib sources have four callbacks: Prepare, Check, Dispatch and Finalize.
|
||||||
// On each iteration of the GLib pump, it calls each source's Prepare function.
|
// On each iteration of the GLib pump, it calls each source's Prepare function.
|
||||||
@@ -102,8 +105,7 @@ struct WorkSource : public GSource {
|
|||||||
MessagePumpGlib* pump;
|
MessagePumpGlib* pump;
|
||||||
};
|
};
|
||||||
|
|
||||||
gboolean WorkSourcePrepare(GSource* source,
|
gboolean WorkSourcePrepare(GSource* source, gint* timeout_ms) {
|
||||||
gint* timeout_ms) {
|
|
||||||
*timeout_ms = static_cast<WorkSource*>(source)->pump->HandlePrepare();
|
*timeout_ms = static_cast<WorkSource*>(source)->pump->HandlePrepare();
|
||||||
// We always return FALSE, so that our timeout is honored. If we were
|
// We always return FALSE, so that our timeout is honored. If we were
|
||||||
// to return TRUE, the timeout would be considered to be 0 and the poll
|
// to return TRUE, the timeout would be considered to be 0 and the poll
|
||||||
@@ -128,52 +130,6 @@ gboolean WorkSourceDispatch(GSource* source,
|
|||||||
GSourceFuncs WorkSourceFuncs = {WorkSourcePrepare, WorkSourceCheck,
|
GSourceFuncs WorkSourceFuncs = {WorkSourcePrepare, WorkSourceCheck,
|
||||||
WorkSourceDispatch, nullptr};
|
WorkSourceDispatch, nullptr};
|
||||||
|
|
||||||
// The following is used to make sure we only run the MessagePumpGlib on one
|
|
||||||
// thread. X only has one message pump so we can only have one UI loop per
|
|
||||||
// process.
|
|
||||||
#ifndef NDEBUG
|
|
||||||
|
|
||||||
// Tracks the pump the most recent pump that has been run.
|
|
||||||
struct ThreadInfo {
|
|
||||||
// The pump.
|
|
||||||
MessagePumpGlib* pump;
|
|
||||||
|
|
||||||
// ID of the thread the pump was run on.
|
|
||||||
PlatformThreadId thread_id;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Used for accesing |thread_info|.
|
|
||||||
Lock& GetThreadInfoLock() {
|
|
||||||
static NoDestructor<Lock> thread_info_lock;
|
|
||||||
return *thread_info_lock;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If non-null it means a MessagePumpGlib exists and has been Run. This is
|
|
||||||
// destroyed when the MessagePump is destroyed.
|
|
||||||
ThreadInfo* g_thread_info = nullptr;
|
|
||||||
|
|
||||||
void CheckThread(MessagePumpGlib* pump) {
|
|
||||||
AutoLock auto_lock(GetThreadInfoLock());
|
|
||||||
if (!g_thread_info) {
|
|
||||||
g_thread_info = new ThreadInfo;
|
|
||||||
g_thread_info->pump = pump;
|
|
||||||
g_thread_info->thread_id = PlatformThread::CurrentId();
|
|
||||||
}
|
|
||||||
DCHECK_EQ(g_thread_info->thread_id, PlatformThread::CurrentId())
|
|
||||||
<< "Running MessagePumpGlib on two different threads; "
|
|
||||||
"this is unsupported by GLib!";
|
|
||||||
}
|
|
||||||
|
|
||||||
void PumpDestroyed(MessagePumpGlib* pump) {
|
|
||||||
AutoLock auto_lock(GetThreadInfoLock());
|
|
||||||
if (g_thread_info && g_thread_info->pump == pump) {
|
|
||||||
delete g_thread_info;
|
|
||||||
g_thread_info = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct FdWatchSource : public GSource {
|
struct FdWatchSource : public GSource {
|
||||||
MessagePumpGlib* pump;
|
MessagePumpGlib* pump;
|
||||||
MessagePumpGlib::FdWatchController* controller;
|
MessagePumpGlib::FdWatchController* controller;
|
||||||
@@ -218,16 +174,23 @@ struct MessagePumpGlib::RunState {
|
|||||||
};
|
};
|
||||||
|
|
||||||
MessagePumpGlib::MessagePumpGlib()
|
MessagePumpGlib::MessagePumpGlib()
|
||||||
: state_(nullptr),
|
: state_(nullptr), wakeup_gpollfd_(std::make_unique<GPollFD>()) {
|
||||||
context_(g_main_context_default()),
|
DCHECK(!g_main_context_get_thread_default());
|
||||||
wakeup_gpollfd_(new GPollFD) {
|
if (RunningOnMainThread()) {
|
||||||
|
context_ = g_main_context_default();
|
||||||
|
} else {
|
||||||
|
context_ = g_main_context_new();
|
||||||
|
g_main_context_push_thread_default(context_);
|
||||||
|
context_owned_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Create our wakeup pipe, which is used to flag when work was scheduled.
|
// Create our wakeup pipe, which is used to flag when work was scheduled.
|
||||||
int fds[2];
|
int fds[2];
|
||||||
int ret = pipe(fds);
|
int ret = pipe(fds);
|
||||||
DCHECK_EQ(ret, 0);
|
DCHECK_EQ(ret, 0);
|
||||||
(void)ret; // Prevent warning in release mode.
|
(void)ret; // Prevent warning in release mode.
|
||||||
|
|
||||||
wakeup_pipe_read_ = fds[0];
|
wakeup_pipe_read_ = fds[0];
|
||||||
wakeup_pipe_write_ = fds[1];
|
wakeup_pipe_write_ = fds[1];
|
||||||
wakeup_gpollfd_->fd = wakeup_pipe_read_;
|
wakeup_gpollfd_->fd = wakeup_pipe_read_;
|
||||||
wakeup_gpollfd_->events = G_IO_IN;
|
wakeup_gpollfd_->events = G_IO_IN;
|
||||||
@@ -242,13 +205,15 @@ MessagePumpGlib::MessagePumpGlib()
|
|||||||
}
|
}
|
||||||
|
|
||||||
MessagePumpGlib::~MessagePumpGlib() {
|
MessagePumpGlib::~MessagePumpGlib() {
|
||||||
#ifndef NDEBUG
|
|
||||||
PumpDestroyed(this);
|
|
||||||
#endif
|
|
||||||
g_source_destroy(work_source_);
|
g_source_destroy(work_source_);
|
||||||
g_source_unref(work_source_);
|
g_source_unref(work_source_);
|
||||||
close(wakeup_pipe_read_);
|
close(wakeup_pipe_read_);
|
||||||
close(wakeup_pipe_write_);
|
close(wakeup_pipe_write_);
|
||||||
|
|
||||||
|
if (context_owned_) {
|
||||||
|
g_main_context_pop_thread_default(context_);
|
||||||
|
g_main_context_unref(context_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MessagePumpGlib::FdWatchController::FdWatchController(const Location& location)
|
MessagePumpGlib::FdWatchController::FdWatchController(const Location& location)
|
||||||
@@ -410,10 +375,6 @@ void MessagePumpGlib::HandleDispatch() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MessagePumpGlib::Run(Delegate* delegate) {
|
void MessagePumpGlib::Run(Delegate* delegate) {
|
||||||
#ifndef NDEBUG
|
|
||||||
CheckThread(this);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
RunState state;
|
RunState state;
|
||||||
state.delegate = delegate;
|
state.delegate = delegate;
|
||||||
state.should_quit = false;
|
state.should_quit = false;
|
||||||
|
@@ -112,10 +112,11 @@ class BASE_EXPORT MessagePumpGlib : public MessagePump,
|
|||||||
|
|
||||||
RunState* state_;
|
RunState* state_;
|
||||||
|
|
||||||
// This is a GLib structure that we can add event sources to. We use the
|
// This is a GLib structure that we can add event sources to. On the main
|
||||||
// default GLib context, which is the one to which all GTK events are
|
// thread, we use the default GLib context, which is the one to which all GTK
|
||||||
// dispatched.
|
// events are dispatched.
|
||||||
GMainContext* context_;
|
GMainContext* context_ = nullptr;
|
||||||
|
bool context_owned_ = false;
|
||||||
|
|
||||||
// The work source. It is shared by all calls to Run and destroyed when
|
// The work source. It is shared by all calls to Run and destroyed when
|
||||||
// the message pump is destroyed.
|
// the message pump is destroyed.
|
||||||
|
@@ -240,11 +240,8 @@ OutputSurfaceProviderImpl::CreateSoftwareOutputDeviceForPlatform(
|
|||||||
ui::OzonePlatform::GetInstance()->GetSurfaceFactoryOzone();
|
ui::OzonePlatform::GetInstance()->GetSurfaceFactoryOzone();
|
||||||
std::unique_ptr<ui::PlatformWindowSurface> platform_window_surface =
|
std::unique_ptr<ui::PlatformWindowSurface> platform_window_surface =
|
||||||
factory->CreatePlatformWindowSurface(surface_handle);
|
factory->CreatePlatformWindowSurface(surface_handle);
|
||||||
scoped_refptr<base::SequencedTaskRunner> main_runner;
|
|
||||||
if (gpu_service_impl_ && !gpu_service_impl_->in_host_process())
|
|
||||||
main_runner = gpu_service_impl_->main_runner();
|
|
||||||
std::unique_ptr<ui::SurfaceOzoneCanvas> surface_ozone =
|
std::unique_ptr<ui::SurfaceOzoneCanvas> surface_ozone =
|
||||||
factory->CreateCanvasForWidget(surface_handle, std::move(main_runner));
|
factory->CreateCanvasForWidget(surface_handle);
|
||||||
CHECK(surface_ozone);
|
CHECK(surface_ozone);
|
||||||
return std::make_unique<SoftwareOutputDeviceOzone>(
|
return std::make_unique<SoftwareOutputDeviceOzone>(
|
||||||
std::move(platform_window_surface), std::move(surface_ozone));
|
std::move(platform_window_surface), std::move(surface_ozone));
|
||||||
@@ -252,11 +249,7 @@ OutputSurfaceProviderImpl::CreateSoftwareOutputDeviceForPlatform(
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(USE_X11)
|
#if defined(USE_X11)
|
||||||
scoped_refptr<base::SequencedTaskRunner> main_runner;
|
return std::make_unique<SoftwareOutputDeviceX11>(surface_handle);
|
||||||
if (gpu_service_impl_ && !gpu_service_impl_->in_host_process())
|
|
||||||
main_runner = gpu_service_impl_->main_runner();
|
|
||||||
return std::make_unique<SoftwareOutputDeviceX11>(surface_handle,
|
|
||||||
std::move(main_runner));
|
|
||||||
#else
|
#else
|
||||||
NOTREACHED();
|
NOTREACHED();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@@ -22,12 +22,8 @@
|
|||||||
|
|
||||||
namespace viz {
|
namespace viz {
|
||||||
|
|
||||||
SoftwareOutputDeviceX11::SoftwareOutputDeviceX11(
|
SoftwareOutputDeviceX11::SoftwareOutputDeviceX11(gfx::AcceleratedWidget widget)
|
||||||
gfx::AcceleratedWidget widget,
|
: x11_software_bitmap_presenter_(widget) {
|
||||||
scoped_refptr<base::SequencedTaskRunner> gpu_task_runner)
|
|
||||||
: x11_software_bitmap_presenter_(widget,
|
|
||||||
task_runner_.get(),
|
|
||||||
std::move(gpu_task_runner)) {
|
|
||||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -19,9 +19,7 @@ namespace viz {
|
|||||||
|
|
||||||
class VIZ_SERVICE_EXPORT SoftwareOutputDeviceX11 : public SoftwareOutputDevice {
|
class VIZ_SERVICE_EXPORT SoftwareOutputDeviceX11 : public SoftwareOutputDevice {
|
||||||
public:
|
public:
|
||||||
SoftwareOutputDeviceX11(
|
explicit SoftwareOutputDeviceX11(gfx::AcceleratedWidget widget);
|
||||||
gfx::AcceleratedWidget widget,
|
|
||||||
scoped_refptr<base::SequencedTaskRunner> gpu_task_runner);
|
|
||||||
|
|
||||||
~SoftwareOutputDeviceX11() override;
|
~SoftwareOutputDeviceX11() override;
|
||||||
|
|
||||||
|
@@ -52,4 +52,8 @@ source_set("main") {
|
|||||||
if (is_chromecast) {
|
if (is_chromecast) {
|
||||||
deps += [ "//chromecast/media/service/mojom" ]
|
deps += [ "//chromecast/media/service/mojom" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (use_x11) {
|
||||||
|
deps += [ "//ui/base/x" ]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -37,6 +37,15 @@
|
|||||||
#include "components/ui_devtools/viz/overlay_agent_viz.h"
|
#include "components/ui_devtools/viz/overlay_agent_viz.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(USE_OZONE)
|
||||||
|
#include "ui/base/ui_base_features.h"
|
||||||
|
#include "ui/ozone/public/ozone_platform.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(USE_X11)
|
||||||
|
#include "ui/base/x/x11_ui_thread.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace viz {
|
namespace viz {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@@ -53,9 +62,25 @@ std::unique_ptr<VizCompositorThreadType> CreateAndStartCompositorThread() {
|
|||||||
thread->Start();
|
thread->Start();
|
||||||
return thread;
|
return thread;
|
||||||
#else // !defined(OS_ANDROID)
|
#else // !defined(OS_ANDROID)
|
||||||
auto thread = std::make_unique<base::Thread>(kThreadName);
|
|
||||||
|
|
||||||
|
std::unique_ptr<base::Thread> thread;
|
||||||
base::Thread::Options thread_options;
|
base::Thread::Options thread_options;
|
||||||
|
#if defined(USE_OZONE)
|
||||||
|
if (features::IsUsingOzonePlatform()) {
|
||||||
|
auto* platform = ui::OzonePlatform::GetInstance();
|
||||||
|
thread_options.message_pump_type =
|
||||||
|
platform->GetPlatformProperties().message_pump_type_for_viz_compositor;
|
||||||
|
thread = std::make_unique<base::Thread>(kThreadName);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if defined(USE_X11)
|
||||||
|
if (!thread) {
|
||||||
|
thread = std::make_unique<ui::X11UiThread>(kThreadName);
|
||||||
|
thread_options.message_pump_type = base::MessagePumpType::UI;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (!thread)
|
||||||
|
thread = std::make_unique<base::Thread>(kThreadName);
|
||||||
|
|
||||||
#if defined(OS_FUCHSIA)
|
#if defined(OS_FUCHSIA)
|
||||||
// An IO message pump is needed to use FIDL.
|
// An IO message pump is needed to use FIDL.
|
||||||
|
@@ -78,6 +78,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(USE_X11)
|
#if defined(USE_X11)
|
||||||
|
#include "ui/base/x/x11_ui_thread.h" // nogncheck
|
||||||
#include "ui/base/x/x11_util.h" // nogncheck
|
#include "ui/base/x/x11_util.h" // nogncheck
|
||||||
#include "ui/gfx/linux/gpu_memory_buffer_support_x11.h" // nogncheck
|
#include "ui/gfx/linux/gpu_memory_buffer_support_x11.h" // nogncheck
|
||||||
#include "ui/gfx/x/x11.h" // nogncheck
|
#include "ui/gfx/x/x11.h" // nogncheck
|
||||||
@@ -286,6 +287,10 @@ int GpuMain(const MainFunctionParams& parameters) {
|
|||||||
std::make_unique<base::SingleThreadTaskExecutor>(
|
std::make_unique<base::SingleThreadTaskExecutor>(
|
||||||
base::MessagePumpType::UI);
|
base::MessagePumpType::UI);
|
||||||
event_source = ui::PlatformEventSource::CreateDefault();
|
event_source = ui::PlatformEventSource::CreateDefault();
|
||||||
|
// Set up the X11UiThread before the sandbox gets set up. This cannot be
|
||||||
|
// done later since opening the connection requires socket() and
|
||||||
|
// connect().
|
||||||
|
ui::X11UiThread::SetConnection(x11::Connection::Get()->Clone().release());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(USE_OZONE)
|
#if defined(USE_OZONE)
|
||||||
|
@@ -42,6 +42,8 @@ component("x") {
|
|||||||
"x11_software_bitmap_presenter.h",
|
"x11_software_bitmap_presenter.h",
|
||||||
"x11_topmost_window_finder.cc",
|
"x11_topmost_window_finder.cc",
|
||||||
"x11_topmost_window_finder.h",
|
"x11_topmost_window_finder.h",
|
||||||
|
"x11_ui_thread.cc",
|
||||||
|
"x11_ui_thread.h",
|
||||||
"x11_util.cc",
|
"x11_util.cc",
|
||||||
"x11_util.h",
|
"x11_util.h",
|
||||||
"x11_whole_screen_move_loop.cc",
|
"x11_whole_screen_move_loop.cc",
|
||||||
|
@@ -113,26 +113,27 @@ XShmImagePool::SwapClosure::SwapClosure() = default;
|
|||||||
|
|
||||||
XShmImagePool::SwapClosure::~SwapClosure() = default;
|
XShmImagePool::SwapClosure::~SwapClosure() = default;
|
||||||
|
|
||||||
XShmImagePool::XShmImagePool(
|
XShmImagePool::XShmImagePool(x11::Connection* connection,
|
||||||
scoped_refptr<base::SequencedTaskRunner> host_task_runner,
|
x11::Drawable drawable,
|
||||||
scoped_refptr<base::SequencedTaskRunner> event_task_runner,
|
Visual* visual,
|
||||||
XDisplay* display,
|
int depth,
|
||||||
x11::Drawable drawable,
|
std::size_t frames_pending)
|
||||||
Visual* visual,
|
: connection_(connection),
|
||||||
int depth,
|
display_(connection_->display()),
|
||||||
std::size_t frames_pending)
|
|
||||||
: host_task_runner_(std::move(host_task_runner)),
|
|
||||||
event_task_runner_(std::move(event_task_runner)),
|
|
||||||
display_(display),
|
|
||||||
drawable_(drawable),
|
drawable_(drawable),
|
||||||
visual_(visual),
|
visual_(visual),
|
||||||
depth_(depth),
|
depth_(depth),
|
||||||
frame_states_(frames_pending) {
|
frame_states_(frames_pending) {
|
||||||
DCHECK(host_task_runner_->RunsTasksInCurrentSequence());
|
X11EventSource::GetInstance()->AddXEventDispatcher(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
XShmImagePool::~XShmImagePool() {
|
||||||
|
Cleanup();
|
||||||
|
X11EventSource::GetInstance()->RemoveXEventDispatcher(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool XShmImagePool::Resize(const gfx::Size& pixel_size) {
|
bool XShmImagePool::Resize(const gfx::Size& pixel_size) {
|
||||||
DCHECK(host_task_runner_->RunsTasksInCurrentSequence());
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
|
|
||||||
if (pixel_size == pixel_size_)
|
if (pixel_size == pixel_size_)
|
||||||
return true;
|
return true;
|
||||||
@@ -141,9 +142,6 @@ bool XShmImagePool::Resize(const gfx::Size& pixel_size) {
|
|||||||
std::unique_ptr<XShmImagePool, decltype(cleanup_fn)> cleanup{this,
|
std::unique_ptr<XShmImagePool, decltype(cleanup_fn)> cleanup{this,
|
||||||
cleanup_fn};
|
cleanup_fn};
|
||||||
|
|
||||||
if (!event_task_runner_)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
#if !defined(OS_CHROMEOS)
|
#if !defined(OS_CHROMEOS)
|
||||||
if (!ShouldUseMitShm(display_))
|
if (!ShouldUseMitShm(display_))
|
||||||
return false;
|
return false;
|
||||||
@@ -246,31 +244,31 @@ bool XShmImagePool::Resize(const gfx::Size& pixel_size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool XShmImagePool::Ready() {
|
bool XShmImagePool::Ready() {
|
||||||
DCHECK(host_task_runner_->RunsTasksInCurrentSequence());
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
return ready_;
|
return ready_;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkBitmap& XShmImagePool::CurrentBitmap() {
|
SkBitmap& XShmImagePool::CurrentBitmap() {
|
||||||
DCHECK(host_task_runner_->RunsTasksInCurrentSequence());
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
|
|
||||||
return frame_states_[current_frame_index_].bitmap;
|
return frame_states_[current_frame_index_].bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkCanvas* XShmImagePool::CurrentCanvas() {
|
SkCanvas* XShmImagePool::CurrentCanvas() {
|
||||||
DCHECK(host_task_runner_->RunsTasksInCurrentSequence());
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
|
|
||||||
return frame_states_[current_frame_index_].canvas.get();
|
return frame_states_[current_frame_index_].canvas.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
XImage* XShmImagePool::CurrentImage() {
|
XImage* XShmImagePool::CurrentImage() {
|
||||||
DCHECK(host_task_runner_->RunsTasksInCurrentSequence());
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
|
|
||||||
return frame_states_[current_frame_index_].image.get();
|
return frame_states_[current_frame_index_].image.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void XShmImagePool::SwapBuffers(
|
void XShmImagePool::SwapBuffers(
|
||||||
base::OnceCallback<void(const gfx::Size&)> callback) {
|
base::OnceCallback<void(const gfx::Size&)> callback) {
|
||||||
DCHECK(host_task_runner_->RunsTasksInCurrentSequence());
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
|
|
||||||
swap_closures_.emplace_back();
|
swap_closures_.emplace_back();
|
||||||
SwapClosure& swap_closure = swap_closures_.back();
|
SwapClosure& swap_closure = swap_closures_.back();
|
||||||
@@ -280,30 +278,9 @@ void XShmImagePool::SwapBuffers(
|
|||||||
current_frame_index_ = (current_frame_index_ + 1) % frame_states_.size();
|
current_frame_index_ = (current_frame_index_ + 1) % frame_states_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void XShmImagePool::Initialize() {
|
|
||||||
DCHECK(host_task_runner_->RunsTasksInCurrentSequence());
|
|
||||||
if (event_task_runner_)
|
|
||||||
event_task_runner_->PostTask(
|
|
||||||
FROM_HERE, base::BindOnce(&XShmImagePool::InitializeOnGpu, this));
|
|
||||||
}
|
|
||||||
|
|
||||||
void XShmImagePool::Teardown() {
|
|
||||||
DCHECK(host_task_runner_->RunsTasksInCurrentSequence());
|
|
||||||
if (event_task_runner_)
|
|
||||||
event_task_runner_->PostTask(
|
|
||||||
FROM_HERE, base::BindOnce(&XShmImagePool::TeardownOnGpu, this));
|
|
||||||
}
|
|
||||||
|
|
||||||
XShmImagePool::~XShmImagePool() {
|
|
||||||
Cleanup();
|
|
||||||
#ifndef NDEBUG
|
|
||||||
DCHECK(!dispatcher_registered_);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void XShmImagePool::DispatchShmCompletionEvent(
|
void XShmImagePool::DispatchShmCompletionEvent(
|
||||||
x11::Shm::CompletionEvent event) {
|
x11::Shm::CompletionEvent event) {
|
||||||
DCHECK(host_task_runner_->RunsTasksInCurrentSequence());
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
DCHECK_EQ(event.offset, 0UL);
|
DCHECK_EQ(event.offset, 0UL);
|
||||||
|
|
||||||
for (auto it = swap_closures_.begin(); it != swap_closures_.end(); ++it) {
|
for (auto it = swap_closures_.begin(); it != swap_closures_.end(); ++it) {
|
||||||
@@ -316,32 +293,16 @@ void XShmImagePool::DispatchShmCompletionEvent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool XShmImagePool::DispatchXEvent(x11::Event* xev) {
|
bool XShmImagePool::DispatchXEvent(x11::Event* xev) {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
|
|
||||||
auto* completion = xev->As<x11::Shm::CompletionEvent>();
|
auto* completion = xev->As<x11::Shm::CompletionEvent>();
|
||||||
if (!completion || completion->drawable.value != drawable_.value)
|
if (!completion || completion->drawable.value != drawable_.value)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
host_task_runner_->PostTask(
|
DispatchShmCompletionEvent(*completion);
|
||||||
FROM_HERE, base::BindOnce(&XShmImagePool::DispatchShmCompletionEvent,
|
|
||||||
this, *completion));
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void XShmImagePool::InitializeOnGpu() {
|
|
||||||
DCHECK(event_task_runner_->RunsTasksInCurrentSequence());
|
|
||||||
X11EventSource::GetInstance()->AddXEventDispatcher(this);
|
|
||||||
#ifndef NDEBUG
|
|
||||||
dispatcher_registered_ = true;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void XShmImagePool::TeardownOnGpu() {
|
|
||||||
DCHECK(event_task_runner_->RunsTasksInCurrentSequence());
|
|
||||||
X11EventSource::GetInstance()->RemoveXEventDispatcher(this);
|
|
||||||
#ifndef NDEBUG
|
|
||||||
dispatcher_registered_ = false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void XShmImagePool::Cleanup() {
|
void XShmImagePool::Cleanup() {
|
||||||
for (FrameState& state : frame_states_) {
|
for (FrameState& state : frame_states_) {
|
||||||
if (state.shminfo_.shmaddr)
|
if (state.shminfo_.shmaddr)
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
#include "base/component_export.h"
|
#include "base/component_export.h"
|
||||||
#include "base/macros.h"
|
#include "base/macros.h"
|
||||||
#include "base/memory/ref_counted.h"
|
#include "base/memory/ref_counted.h"
|
||||||
#include "base/task_runner.h"
|
#include "base/sequence_checker.h"
|
||||||
#include "third_party/skia/include/core/SkBitmap.h"
|
#include "third_party/skia/include/core/SkBitmap.h"
|
||||||
#include "third_party/skia/include/core/SkCanvas.h"
|
#include "third_party/skia/include/core/SkCanvas.h"
|
||||||
#include "ui/base/x/x11_util.h"
|
#include "ui/base/x/x11_util.h"
|
||||||
@@ -25,22 +25,18 @@
|
|||||||
|
|
||||||
namespace ui {
|
namespace ui {
|
||||||
|
|
||||||
// Base class that creates XImages using shared memory that will be sent to
|
// Creates XImages backed by shared memory that will be shared with the X11
|
||||||
// XServer for processing. As Ozone and non-Ozone X11 have different
|
// server for processing.
|
||||||
// PlatformEvent types, Ozone and non-Ozone provide own implementations that
|
class COMPONENT_EXPORT(UI_BASE_X) XShmImagePool : public XEventDispatcher {
|
||||||
// handles events. See AddEventDispatcher and RemoveEventDispatcher below.
|
|
||||||
class COMPONENT_EXPORT(UI_BASE_X) XShmImagePool
|
|
||||||
: public base::RefCountedThreadSafe<XShmImagePool>,
|
|
||||||
public XEventDispatcher {
|
|
||||||
public:
|
public:
|
||||||
XShmImagePool(scoped_refptr<base::SequencedTaskRunner> host_task_runner,
|
XShmImagePool(x11::Connection* connection,
|
||||||
scoped_refptr<base::SequencedTaskRunner> event_task_runner,
|
|
||||||
XDisplay* display,
|
|
||||||
x11::Drawable drawable,
|
x11::Drawable drawable,
|
||||||
Visual* visual,
|
Visual* visual,
|
||||||
int depth,
|
int depth,
|
||||||
std::size_t max_frames_pending);
|
std::size_t max_frames_pending);
|
||||||
|
|
||||||
|
~XShmImagePool() override;
|
||||||
|
|
||||||
bool Resize(const gfx::Size& pixel_size);
|
bool Resize(const gfx::Size& pixel_size);
|
||||||
|
|
||||||
// Is XSHM supported by the server and are the shared buffers ready for use?
|
// Is XSHM supported by the server and are the shared buffers ready for use?
|
||||||
@@ -55,26 +51,9 @@ class COMPONENT_EXPORT(UI_BASE_X) XShmImagePool
|
|||||||
// change to reflect the new frame.
|
// change to reflect the new frame.
|
||||||
void SwapBuffers(base::OnceCallback<void(const gfx::Size&)> callback);
|
void SwapBuffers(base::OnceCallback<void(const gfx::Size&)> callback);
|
||||||
|
|
||||||
// Part of setup and teardown must be done on the event task runner. Posting
|
|
||||||
// the tasks cannot be done in the constructor/destructor because because this
|
|
||||||
// would cause subtle problems with the reference count for this object. So
|
|
||||||
// Initialize() must be called after constructing and Teardown() must be
|
|
||||||
// called before destructing.
|
|
||||||
void Initialize();
|
|
||||||
void Teardown();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
~XShmImagePool() override;
|
|
||||||
|
|
||||||
void DispatchShmCompletionEvent(x11::Shm::CompletionEvent event);
|
void DispatchShmCompletionEvent(x11::Shm::CompletionEvent event);
|
||||||
|
|
||||||
const scoped_refptr<base::SequencedTaskRunner> host_task_runner_;
|
|
||||||
const scoped_refptr<base::SequencedTaskRunner> event_task_runner_;
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
bool dispatcher_registered_ = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class base::RefCountedThreadSafe<XShmImagePool>;
|
friend class base::RefCountedThreadSafe<XShmImagePool>;
|
||||||
|
|
||||||
@@ -100,11 +79,9 @@ class COMPONENT_EXPORT(UI_BASE_X) XShmImagePool
|
|||||||
// XEventDispatcher:
|
// XEventDispatcher:
|
||||||
bool DispatchXEvent(x11::Event* xev) override;
|
bool DispatchXEvent(x11::Event* xev) override;
|
||||||
|
|
||||||
void InitializeOnGpu();
|
|
||||||
void TeardownOnGpu();
|
|
||||||
|
|
||||||
void Cleanup();
|
void Cleanup();
|
||||||
|
|
||||||
|
x11::Connection* const connection_;
|
||||||
XDisplay* const display_;
|
XDisplay* const display_;
|
||||||
const x11::Drawable drawable_;
|
const x11::Drawable drawable_;
|
||||||
Visual* const visual_;
|
Visual* const visual_;
|
||||||
@@ -117,6 +94,8 @@ class COMPONENT_EXPORT(UI_BASE_X) XShmImagePool
|
|||||||
std::size_t current_frame_index_ = 0;
|
std::size_t current_frame_index_ = 0;
|
||||||
std::list<SwapClosure> swap_closures_;
|
std::list<SwapClosure> swap_closures_;
|
||||||
|
|
||||||
|
SEQUENCE_CHECKER(sequence_checker_);
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(XShmImagePool);
|
DISALLOW_COPY_AND_ASSIGN(XShmImagePool);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
#include "base/bind.h"
|
#include "base/bind.h"
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
#include "base/macros.h"
|
#include "base/macros.h"
|
||||||
|
#include "base/task/current_thread.h"
|
||||||
#include "third_party/skia/include/core/SkCanvas.h"
|
#include "third_party/skia/include/core/SkCanvas.h"
|
||||||
#include "third_party/skia/include/core/SkImageInfo.h"
|
#include "third_party/skia/include/core/SkImageInfo.h"
|
||||||
#include "third_party/skia/include/core/SkSurface.h"
|
#include "third_party/skia/include/core/SkSurface.h"
|
||||||
@@ -122,15 +123,12 @@ bool X11SoftwareBitmapPresenter::CompositeBitmap(XDisplay* display,
|
|||||||
}
|
}
|
||||||
|
|
||||||
X11SoftwareBitmapPresenter::X11SoftwareBitmapPresenter(
|
X11SoftwareBitmapPresenter::X11SoftwareBitmapPresenter(
|
||||||
gfx::AcceleratedWidget widget,
|
gfx::AcceleratedWidget widget)
|
||||||
scoped_refptr<base::SequencedTaskRunner> host_task_runner,
|
|
||||||
scoped_refptr<base::SequencedTaskRunner> event_task_runner)
|
|
||||||
: widget_(static_cast<x11::Window>(widget)),
|
: widget_(static_cast<x11::Window>(widget)),
|
||||||
display_(gfx::GetXDisplay()),
|
connection_(x11::Connection::Get()),
|
||||||
gc_(nullptr),
|
display_(connection_->display()),
|
||||||
host_task_runner_(host_task_runner),
|
gc_(nullptr) {
|
||||||
event_task_runner_(event_task_runner) {
|
DCHECK_NE(widget_, x11::Window::None);
|
||||||
DCHECK(widget_ != x11::Window::None);
|
|
||||||
gc_ = XCreateGC(display_, static_cast<uint32_t>(widget_), 0, nullptr);
|
gc_ = XCreateGC(display_, static_cast<uint32_t>(widget_), 0, nullptr);
|
||||||
memset(&attributes_, 0, sizeof(attributes_));
|
memset(&attributes_, 0, sizeof(attributes_));
|
||||||
if (!XGetWindowAttributes(display_, static_cast<uint32_t>(widget_),
|
if (!XGetWindowAttributes(display_, static_cast<uint32_t>(widget_),
|
||||||
@@ -140,10 +138,9 @@ X11SoftwareBitmapPresenter::X11SoftwareBitmapPresenter(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
shm_pool_ = base::MakeRefCounted<ui::XShmImagePool>(
|
shm_pool_ = std::make_unique<ui::XShmImagePool>(
|
||||||
host_task_runner, event_task_runner, display_, widget_,
|
connection_, widget_, attributes_.visual, attributes_.depth,
|
||||||
attributes_.visual, attributes_.depth, kMaxFramesPending);
|
kMaxFramesPending);
|
||||||
shm_pool_->Initialize();
|
|
||||||
|
|
||||||
// TODO(thomasanderson): Avoid going through the X11 server to plumb this
|
// TODO(thomasanderson): Avoid going through the X11 server to plumb this
|
||||||
// property in.
|
// property in.
|
||||||
@@ -151,41 +148,17 @@ X11SoftwareBitmapPresenter::X11SoftwareBitmapPresenter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
X11SoftwareBitmapPresenter::~X11SoftwareBitmapPresenter() {
|
X11SoftwareBitmapPresenter::~X11SoftwareBitmapPresenter() {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
if (gc_)
|
if (gc_)
|
||||||
XFreeGC(display_, gc_);
|
XFreeGC(display_, gc_);
|
||||||
|
|
||||||
if (shm_pool_)
|
|
||||||
shm_pool_->Teardown();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool X11SoftwareBitmapPresenter::ShmPoolReady() const {
|
bool X11SoftwareBitmapPresenter::ShmPoolReady() const {
|
||||||
return shm_pool_ && shm_pool_->Ready();
|
return shm_pool_ && shm_pool_->Ready();
|
||||||
}
|
}
|
||||||
|
|
||||||
void X11SoftwareBitmapPresenter::FlushAfterPutImage() {
|
|
||||||
// Ensure the new window content appears immediately. On a TYPE_UI thread we
|
|
||||||
// can rely on the message loop to flush for us so XFlush() isn't necessary.
|
|
||||||
// However, this code can run on a different thread and would have to wait for
|
|
||||||
// the TYPE_UI thread to no longer be idle before a flush happens.
|
|
||||||
XFlush(display_);
|
|
||||||
|
|
||||||
// Work around a race condition caused by XFlush above. Explanation: XFlush()
|
|
||||||
// flushes all requests and *also* reads events. It's unclear why it does
|
|
||||||
// this, but there's no alternative Xlib function that flushes the requests
|
|
||||||
// and *doesn't* read any events, so this workaround is necessary. In
|
|
||||||
// |event_task_runner_|'s message loop, poll() is called on the underlying
|
|
||||||
// XDisplay's fd to dispatch toplevel events. When the fd is readable, poll()
|
|
||||||
// exits and we (via Xlib) check for new events by read()ing from the fd. But
|
|
||||||
// if the event dispatcher is currently dispatching an event, then our call to
|
|
||||||
// XFlush() may read events into the event queue which will make the fd
|
|
||||||
// blocking since there's no more data to read, so poll() won't wake up until
|
|
||||||
// a new event comes, which may take a long time. Forcing the event loop to
|
|
||||||
// wake up with a dummy event fixes the race condition.
|
|
||||||
if (event_task_runner_)
|
|
||||||
event_task_runner_->PostTask(FROM_HERE, base::BindOnce([] {}));
|
|
||||||
}
|
|
||||||
|
|
||||||
void X11SoftwareBitmapPresenter::Resize(const gfx::Size& pixel_size) {
|
void X11SoftwareBitmapPresenter::Resize(const gfx::Size& pixel_size) {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
if (pixel_size == viewport_pixel_size_)
|
if (pixel_size == viewport_pixel_size_)
|
||||||
return;
|
return;
|
||||||
viewport_pixel_size_ = pixel_size;
|
viewport_pixel_size_ = pixel_size;
|
||||||
@@ -209,6 +182,7 @@ void X11SoftwareBitmapPresenter::Resize(const gfx::Size& pixel_size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SkCanvas* X11SoftwareBitmapPresenter::GetSkCanvas() {
|
SkCanvas* X11SoftwareBitmapPresenter::GetSkCanvas() {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
if (ShmPoolReady())
|
if (ShmPoolReady())
|
||||||
return shm_pool_->CurrentCanvas();
|
return shm_pool_->CurrentCanvas();
|
||||||
else if (surface_)
|
else if (surface_)
|
||||||
@@ -217,6 +191,7 @@ SkCanvas* X11SoftwareBitmapPresenter::GetSkCanvas() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void X11SoftwareBitmapPresenter::EndPaint(const gfx::Rect& damage_rect) {
|
void X11SoftwareBitmapPresenter::EndPaint(const gfx::Rect& damage_rect) {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
gfx::Rect rect = damage_rect;
|
gfx::Rect rect = damage_rect;
|
||||||
rect.Intersect(gfx::Rect(viewport_pixel_size_));
|
rect.Intersect(gfx::Rect(viewport_pixel_size_));
|
||||||
if (rect.IsEmpty())
|
if (rect.IsEmpty())
|
||||||
@@ -231,7 +206,6 @@ void X11SoftwareBitmapPresenter::EndPaint(const gfx::Rect& damage_rect) {
|
|||||||
shm_pool_->CurrentImage(), rect.x(), rect.y(), rect.x(),
|
shm_pool_->CurrentImage(), rect.x(), rect.y(), rect.x(),
|
||||||
rect.y(), rect.width(), rect.height(), x11::True)) {
|
rect.y(), rect.width(), rect.height(), x11::True)) {
|
||||||
needs_swap_ = true;
|
needs_swap_ = true;
|
||||||
FlushAfterPutImage();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
skia_pixmap = shm_pool_->CurrentBitmap().pixmap();
|
skia_pixmap = shm_pool_->CurrentBitmap().pixmap();
|
||||||
@@ -246,7 +220,6 @@ void X11SoftwareBitmapPresenter::EndPaint(const gfx::Rect& damage_rect) {
|
|||||||
CompositeBitmap(display_, static_cast<uint32_t>(widget_), rect.x(),
|
CompositeBitmap(display_, static_cast<uint32_t>(widget_), rect.x(),
|
||||||
rect.y(), rect.width(), rect.height(), attributes_.depth,
|
rect.y(), rect.width(), rect.height(), attributes_.depth,
|
||||||
gc_, skia_pixmap.addr())) {
|
gc_, skia_pixmap.addr())) {
|
||||||
FlushAfterPutImage();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,22 +230,18 @@ void X11SoftwareBitmapPresenter::EndPaint(const gfx::Rect& damage_rect) {
|
|||||||
gc, skia_pixmap, rect.x(), rect.y(), rect.x(), rect.y(),
|
gc, skia_pixmap, rect.x(), rect.y(), rect.x(), rect.y(),
|
||||||
rect.width(), rect.height());
|
rect.width(), rect.height());
|
||||||
|
|
||||||
FlushAfterPutImage();
|
// We must be running on a UI thread so that the connection will be flushed.
|
||||||
|
DCHECK(base::CurrentUIThread::IsSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
void X11SoftwareBitmapPresenter::OnSwapBuffers(
|
void X11SoftwareBitmapPresenter::OnSwapBuffers(
|
||||||
SwapBuffersCallback swap_ack_callback) {
|
SwapBuffersCallback swap_ack_callback) {
|
||||||
if (ShmPoolReady()) {
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
if (needs_swap_)
|
if (ShmPoolReady() && needs_swap_)
|
||||||
shm_pool_->SwapBuffers(std::move(swap_ack_callback));
|
shm_pool_->SwapBuffers(std::move(swap_ack_callback));
|
||||||
else
|
else
|
||||||
std::move(swap_ack_callback).Run(viewport_pixel_size_);
|
std::move(swap_ack_callback).Run(viewport_pixel_size_);
|
||||||
needs_swap_ = false;
|
needs_swap_ = false;
|
||||||
} else {
|
|
||||||
host_task_runner_->PostTask(
|
|
||||||
FROM_HERE,
|
|
||||||
base::BindOnce(std::move(swap_ack_callback), viewport_pixel_size_));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int X11SoftwareBitmapPresenter::MaxFramesPending() const {
|
int X11SoftwareBitmapPresenter::MaxFramesPending() const {
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
#include "base/component_export.h"
|
#include "base/component_export.h"
|
||||||
#include "base/macros.h"
|
#include "base/macros.h"
|
||||||
#include "base/memory/scoped_refptr.h"
|
#include "base/memory/scoped_refptr.h"
|
||||||
|
#include "base/sequence_checker.h"
|
||||||
#include "base/sequenced_task_runner.h"
|
#include "base/sequenced_task_runner.h"
|
||||||
#include "third_party/skia/include/core/SkRefCnt.h"
|
#include "third_party/skia/include/core/SkRefCnt.h"
|
||||||
#include "third_party/skia/include/core/SkSurface.h"
|
#include "third_party/skia/include/core/SkSurface.h"
|
||||||
@@ -28,10 +29,7 @@ class COMPONENT_EXPORT(UI_BASE_X) X11SoftwareBitmapPresenter {
|
|||||||
// Corresponds to SwapBuffersCallback alias in SoftwareOutputDevice.
|
// Corresponds to SwapBuffersCallback alias in SoftwareOutputDevice.
|
||||||
using SwapBuffersCallback = base::OnceCallback<void(const gfx::Size&)>;
|
using SwapBuffersCallback = base::OnceCallback<void(const gfx::Size&)>;
|
||||||
|
|
||||||
X11SoftwareBitmapPresenter(
|
explicit X11SoftwareBitmapPresenter(gfx::AcceleratedWidget widget);
|
||||||
gfx::AcceleratedWidget widget,
|
|
||||||
scoped_refptr<base::SequencedTaskRunner> host_task_runner,
|
|
||||||
scoped_refptr<base::SequencedTaskRunner> event_task_runner);
|
|
||||||
|
|
||||||
~X11SoftwareBitmapPresenter();
|
~X11SoftwareBitmapPresenter();
|
||||||
|
|
||||||
@@ -56,9 +54,8 @@ class COMPONENT_EXPORT(UI_BASE_X) X11SoftwareBitmapPresenter {
|
|||||||
|
|
||||||
bool ShmPoolReady() const;
|
bool ShmPoolReady() const;
|
||||||
|
|
||||||
void FlushAfterPutImage();
|
|
||||||
|
|
||||||
x11::Window widget_;
|
x11::Window widget_;
|
||||||
|
x11::Connection* connection_;
|
||||||
XDisplay* display_;
|
XDisplay* display_;
|
||||||
GC gc_;
|
GC gc_;
|
||||||
XWindowAttributes attributes_;
|
XWindowAttributes attributes_;
|
||||||
@@ -67,15 +64,15 @@ class COMPONENT_EXPORT(UI_BASE_X) X11SoftwareBitmapPresenter {
|
|||||||
// parent-relative background.
|
// parent-relative background.
|
||||||
int composite_ = 0;
|
int composite_ = 0;
|
||||||
|
|
||||||
scoped_refptr<ui::XShmImagePool> shm_pool_;
|
std::unique_ptr<ui::XShmImagePool> shm_pool_;
|
||||||
bool needs_swap_ = false;
|
bool needs_swap_ = false;
|
||||||
|
|
||||||
scoped_refptr<base::SequencedTaskRunner> host_task_runner_;
|
|
||||||
scoped_refptr<base::SequencedTaskRunner> event_task_runner_;
|
|
||||||
sk_sp<SkSurface> surface_;
|
sk_sp<SkSurface> surface_;
|
||||||
|
|
||||||
gfx::Size viewport_pixel_size_;
|
gfx::Size viewport_pixel_size_;
|
||||||
|
|
||||||
|
SEQUENCE_CHECKER(sequence_checker_);
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(X11SoftwareBitmapPresenter);
|
DISALLOW_COPY_AND_ASSIGN(X11SoftwareBitmapPresenter);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
49
ui/base/x/x11_ui_thread.cc
Normal file
49
ui/base/x/x11_ui_thread.cc
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
// Copyright 2020 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/base/x/x11_ui_thread.h"
|
||||||
|
|
||||||
|
#include "ui/events/platform/x11/x11_event_source.h"
|
||||||
|
#include "ui/gfx/x/connection.h"
|
||||||
|
|
||||||
|
namespace ui {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
x11::Connection* g_connection = nullptr;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
X11UiThread::X11UiThread(const std::string& thread_name)
|
||||||
|
: base::Thread(thread_name) {
|
||||||
|
connection_.reset(g_connection);
|
||||||
|
g_connection = nullptr;
|
||||||
|
// When using in-process GPU, g_connection doesn't get set. But we can just
|
||||||
|
// open a new connection now since there's no GPU sandbox in place.
|
||||||
|
if (!connection_)
|
||||||
|
connection_ = x11::Connection::Get()->Clone();
|
||||||
|
connection_->DetachFromSequence();
|
||||||
|
}
|
||||||
|
|
||||||
|
X11UiThread::~X11UiThread() = default;
|
||||||
|
|
||||||
|
void X11UiThread::SetConnection(x11::Connection* connection) {
|
||||||
|
DCHECK(!g_connection);
|
||||||
|
g_connection = connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
void X11UiThread::Init() {
|
||||||
|
// Connection and X11EventSource make use of TLS, so these calls must be made
|
||||||
|
// on the thread, not in the constructor/destructor.
|
||||||
|
auto* connection = connection_.get();
|
||||||
|
x11::Connection::Set(std::move(connection_));
|
||||||
|
event_source_ = std::make_unique<X11EventSource>(connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
void X11UiThread::CleanUp() {
|
||||||
|
event_source_.reset();
|
||||||
|
connection_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ui
|
48
ui/base/x/x11_ui_thread.h
Normal file
48
ui/base/x/x11_ui_thread.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
// Copyright 2020 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_BASE_X_X11_UI_THREAD_H_
|
||||||
|
#define UI_BASE_X_X11_UI_THREAD_H_
|
||||||
|
|
||||||
|
#include "base/component_export.h"
|
||||||
|
#include "base/threading/thread.h"
|
||||||
|
|
||||||
|
namespace x11 {
|
||||||
|
class Connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace ui {
|
||||||
|
|
||||||
|
class X11EventSource;
|
||||||
|
|
||||||
|
// A thread-local x11::Connection may be used on this thread, stored in TLS and
|
||||||
|
// obtained via x11::Connection::Get(). X11 events for the connection may also
|
||||||
|
// dispatch events on this thread. This thread must be started as TYPE_UI.
|
||||||
|
// TODO(thomasanderson): This can be removed once Linux switches to ozone.
|
||||||
|
class COMPONENT_EXPORT(UI_BASE_X) X11UiThread : public base::Thread {
|
||||||
|
public:
|
||||||
|
explicit X11UiThread(const std::string& thread_name);
|
||||||
|
|
||||||
|
~X11UiThread() override;
|
||||||
|
|
||||||
|
X11UiThread(const X11UiThread&) = delete;
|
||||||
|
X11UiThread& operator=(const X11UiThread&) = delete;
|
||||||
|
|
||||||
|
// Sets the global connection which will have its ownership transferred to the
|
||||||
|
// next X11UiThread created.
|
||||||
|
static void SetConnection(x11::Connection* connection);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// base::Thread:
|
||||||
|
void Init() override;
|
||||||
|
void CleanUp() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<x11::Connection> connection_;
|
||||||
|
std::unique_ptr<X11EventSource> event_source_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ui
|
||||||
|
|
||||||
|
#endif // UI_BASE_X_X11_UI_THREAD_H_
|
@@ -198,8 +198,7 @@ DeviceDataManagerX11* DeviceDataManagerX11::GetInstance() {
|
|||||||
|
|
||||||
DeviceDataManagerX11::DeviceDataManagerX11()
|
DeviceDataManagerX11::DeviceDataManagerX11()
|
||||||
: xi_opcode_(-1),
|
: xi_opcode_(-1),
|
||||||
high_precision_scrolling_disabled_(IsHighPrecisionScrollingDisabled()),
|
high_precision_scrolling_disabled_(IsHighPrecisionScrollingDisabled()) {
|
||||||
button_map_count_(0) {
|
|
||||||
CHECK(x11::Connection::Get());
|
CHECK(x11::Connection::Get());
|
||||||
InitializeXInputInternal();
|
InitializeXInputInternal();
|
||||||
|
|
||||||
@@ -651,13 +650,14 @@ void DeviceDataManagerX11::GetMetricsData(const x11::Event& xev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int DeviceDataManagerX11::GetMappedButton(int button) {
|
int DeviceDataManagerX11::GetMappedButton(int button) {
|
||||||
return button > 0 && button <= button_map_count_ ? button_map_[button - 1]
|
return button > 0 && static_cast<unsigned int>(button) <= button_map_.size()
|
||||||
: button;
|
? button_map_[button - 1]
|
||||||
|
: button;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceDataManagerX11::UpdateButtonMap() {
|
void DeviceDataManagerX11::UpdateButtonMap() {
|
||||||
button_map_count_ = XGetPointerMapping(gfx::GetXDisplay(), button_map_,
|
if (auto reply = x11::Connection::Get()->GetPointerMapping({}).Sync())
|
||||||
base::size(button_map_));
|
button_map_ = std::move(reply->map);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceDataManagerX11::GetGestureTimes(const x11::Event& xev,
|
void DeviceDataManagerX11::GetGestureTimes(const x11::Event& xev,
|
||||||
|
@@ -391,8 +391,7 @@ class EVENTS_DEVICES_X11_EXPORT DeviceDataManagerX11
|
|||||||
// devices when they are re-enabled.
|
// devices when they are re-enabled.
|
||||||
std::map<x11::Input::DeviceId, ui::InputDevice> blocked_keyboard_devices_;
|
std::map<x11::Input::DeviceId, ui::InputDevice> blocked_keyboard_devices_;
|
||||||
|
|
||||||
unsigned char button_map_[256];
|
std::vector<uint8_t> button_map_;
|
||||||
int button_map_count_;
|
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(DeviceDataManagerX11);
|
DISALLOW_COPY_AND_ASSIGN(DeviceDataManagerX11);
|
||||||
};
|
};
|
||||||
|
@@ -123,17 +123,12 @@ using X11EventWatcherImpl = X11EventWatcherGlib;
|
|||||||
using X11EventWatcherImpl = X11EventWatcherFdWatch;
|
using X11EventWatcherImpl = X11EventWatcherFdWatch;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
X11EventSource* X11EventSource::instance_ = nullptr;
|
|
||||||
|
|
||||||
X11EventSource::X11EventSource(x11::Connection* connection)
|
X11EventSource::X11EventSource(x11::Connection* connection)
|
||||||
: watcher_(std::make_unique<X11EventWatcherImpl>(this)),
|
: watcher_(std::make_unique<X11EventWatcherImpl>(this)),
|
||||||
connection_(connection),
|
connection_(connection),
|
||||||
dispatching_event_(nullptr),
|
dispatching_event_(nullptr),
|
||||||
dummy_initialized_(false),
|
dummy_initialized_(false),
|
||||||
distribution_(0, 999) {
|
distribution_(0, 999) {
|
||||||
DCHECK(!instance_);
|
|
||||||
instance_ = this;
|
|
||||||
|
|
||||||
DCHECK(connection_);
|
DCHECK(connection_);
|
||||||
DeviceDataManagerX11::CreateInstance();
|
DeviceDataManagerX11::CreateInstance();
|
||||||
InitializeXkb(connection_);
|
InitializeXkb(connection_);
|
||||||
@@ -142,20 +137,18 @@ X11EventSource::X11EventSource(x11::Connection* connection)
|
|||||||
}
|
}
|
||||||
|
|
||||||
X11EventSource::~X11EventSource() {
|
X11EventSource::~X11EventSource() {
|
||||||
DCHECK_EQ(this, instance_);
|
|
||||||
instance_ = nullptr;
|
|
||||||
if (dummy_initialized_)
|
if (dummy_initialized_)
|
||||||
connection_->DestroyWindow({dummy_window_});
|
connection_->DestroyWindow({dummy_window_});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
bool X11EventSource::HasInstance() {
|
bool X11EventSource::HasInstance() {
|
||||||
return instance_;
|
return GetInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
X11EventSource* X11EventSource::GetInstance() {
|
X11EventSource* X11EventSource::GetInstance() {
|
||||||
DCHECK(instance_);
|
return static_cast<X11EventSource*>(PlatformEventSource::GetInstance());
|
||||||
return instance_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@@ -200,8 +200,6 @@ class EVENTS_EXPORT X11EventSource : public PlatformEventSource,
|
|||||||
|
|
||||||
void RestoreOverridenXEventDispatcher();
|
void RestoreOverridenXEventDispatcher();
|
||||||
|
|
||||||
static X11EventSource* instance_;
|
|
||||||
|
|
||||||
std::unique_ptr<X11EventWatcher> watcher_;
|
std::unique_ptr<X11EventWatcher> watcher_;
|
||||||
|
|
||||||
// The connection to the X11 server used to receive the events.
|
// The connection to the X11 server used to receive the events.
|
||||||
|
@@ -61,7 +61,8 @@ void X11EventWatcherGlib::StartWatching() {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
XDisplay* display = event_source_->connection()->display();
|
XDisplay* display = event_source_->connection()->display();
|
||||||
DCHECK(display) << "Unable to get connection to X server";
|
if (!display)
|
||||||
|
return;
|
||||||
|
|
||||||
x_poll_ = std::make_unique<GPollFD>();
|
x_poll_ = std::make_unique<GPollFD>();
|
||||||
x_poll_->fd = ConnectionNumber(display);
|
x_poll_->fd = ConnectionNumber(display);
|
||||||
@@ -77,7 +78,10 @@ void X11EventWatcherGlib::StartWatching() {
|
|||||||
g_source_add_poll(x_source_, x_poll_.get());
|
g_source_add_poll(x_source_, x_poll_.get());
|
||||||
g_source_set_can_recurse(x_source_, TRUE);
|
g_source_set_can_recurse(x_source_, TRUE);
|
||||||
g_source_set_callback(x_source_, nullptr, event_source_, nullptr);
|
g_source_set_callback(x_source_, nullptr, event_source_, nullptr);
|
||||||
g_source_attach(x_source_, g_main_context_default());
|
auto* context = g_main_context_get_thread_default();
|
||||||
|
if (!context)
|
||||||
|
context = g_main_context_default();
|
||||||
|
g_source_attach(x_source_, context);
|
||||||
started_ = true;
|
started_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -83,6 +83,7 @@ component("xprotos") {
|
|||||||
":gen_xprotos",
|
":gen_xprotos",
|
||||||
"//base",
|
"//base",
|
||||||
"//base:i18n",
|
"//base:i18n",
|
||||||
|
"//ui/events/platform",
|
||||||
]
|
]
|
||||||
sources = get_target_outputs(":gen_xprotos") + [
|
sources = get_target_outputs(":gen_xprotos") + [
|
||||||
"xproto_internal.h",
|
"xproto_internal.h",
|
||||||
|
3
ui/gfx/x/DEPS
Normal file
3
ui/gfx/x/DEPS
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
include_rules = [
|
||||||
|
"+ui/events/platform/platform_event_source.h",
|
||||||
|
]
|
@@ -14,7 +14,9 @@
|
|||||||
#include "base/command_line.h"
|
#include "base/command_line.h"
|
||||||
#include "base/i18n/case_conversion.h"
|
#include "base/i18n/case_conversion.h"
|
||||||
#include "base/memory/scoped_refptr.h"
|
#include "base/memory/scoped_refptr.h"
|
||||||
|
#include "base/no_destructor.h"
|
||||||
#include "base/strings/string16.h"
|
#include "base/strings/string16.h"
|
||||||
|
#include "base/threading/thread_local.h"
|
||||||
#include "ui/gfx/x/bigreq.h"
|
#include "ui/gfx/x/bigreq.h"
|
||||||
#include "ui/gfx/x/event.h"
|
#include "ui/gfx/x/event.h"
|
||||||
#include "ui/gfx/x/randr.h"
|
#include "ui/gfx/x/randr.h"
|
||||||
@@ -201,11 +203,30 @@ bool IsPrivateKeypadKey(KeySym keysym) {
|
|||||||
return key >= 0x11000000 && key <= 0x1100FFFF;
|
return key >= 0x11000000 && key <= 0x1100FFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
base::ThreadLocalOwnedPointer<Connection>& GetConnectionTLS() {
|
||||||
|
static base::NoDestructor<base::ThreadLocalOwnedPointer<Connection>> tls;
|
||||||
|
return *tls;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
// static
|
||||||
Connection* Connection::Get() {
|
Connection* Connection::Get() {
|
||||||
static Connection* instance = new Connection;
|
auto& tls = GetConnectionTLS();
|
||||||
return instance;
|
if (Connection* connection = tls.Get())
|
||||||
|
return connection;
|
||||||
|
auto connection = std::make_unique<Connection>();
|
||||||
|
auto* p_connection = connection.get();
|
||||||
|
tls.Set(std::move(connection));
|
||||||
|
return p_connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void Connection::Set(std::unique_ptr<x11::Connection> connection) {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(connection->sequence_checker_);
|
||||||
|
auto& tls = GetConnectionTLS();
|
||||||
|
DCHECK(!tls.Get());
|
||||||
|
tls.Set(std::move(connection));
|
||||||
}
|
}
|
||||||
|
|
||||||
Connection::Connection(const std::string& address)
|
Connection::Connection(const std::string& address)
|
||||||
@@ -256,11 +277,14 @@ Connection::Connection(const std::string& address)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Connection::~Connection() {
|
Connection::~Connection() {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
|
platform_event_source.reset();
|
||||||
if (display_)
|
if (display_)
|
||||||
XCloseDisplay(display_);
|
XCloseDisplay(display_);
|
||||||
}
|
}
|
||||||
|
|
||||||
xcb_connection_t* Connection::XcbConnection() {
|
xcb_connection_t* Connection::XcbConnection() {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
if (!display())
|
if (!display())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return XGetXCBConnection(display());
|
return XGetXCBConnection(display());
|
||||||
@@ -282,6 +306,7 @@ bool Connection::HasNextResponse() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int Connection::DefaultScreenId() const {
|
int Connection::DefaultScreenId() const {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
// This is not part of the setup data as the server has no concept of a
|
// This is not part of the setup data as the server has no concept of a
|
||||||
// default screen. Instead, it's part of the display name. Eg in
|
// default screen. Instead, it's part of the display name. Eg in
|
||||||
// "localhost:0.0", the screen ID is the second "0".
|
// "localhost:0.0", the screen ID is the second "0".
|
||||||
@@ -289,19 +314,23 @@ int Connection::DefaultScreenId() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Connection::Ready() const {
|
bool Connection::Ready() const {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
return display_ && !xcb_connection_has_error(XGetXCBConnection(display_));
|
return display_ && !xcb_connection_has_error(XGetXCBConnection(display_));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::Flush() {
|
void Connection::Flush() {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
if (display_)
|
if (display_)
|
||||||
XFlush(display_);
|
XFlush(display_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::Sync() {
|
void Connection::Sync() {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
GetInputFocus({}).Sync();
|
GetInputFocus({}).Sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::ReadResponses() {
|
void Connection::ReadResponses() {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
while (auto* event = xcb_poll_for_event(XcbConnection())) {
|
while (auto* event = xcb_poll_for_event(XcbConnection())) {
|
||||||
events_.emplace_back(base::MakeRefCounted<MallocedRefCountedMemory>(event),
|
events_.emplace_back(base::MakeRefCounted<MallocedRefCountedMemory>(event),
|
||||||
this);
|
this);
|
||||||
@@ -309,11 +338,13 @@ void Connection::ReadResponses() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Connection::HasPendingResponses() const {
|
bool Connection::HasPendingResponses() const {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
return !events_.empty() || HasNextResponse();
|
return !events_.empty() || HasNextResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Connection::VisualInfo* Connection::GetVisualInfoFromId(
|
const Connection::VisualInfo* Connection::GetVisualInfoFromId(
|
||||||
VisualId id) const {
|
VisualId id) const {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
auto it = default_screen_visuals_.find(id);
|
auto it = default_screen_visuals_.find(id);
|
||||||
if (it != default_screen_visuals_.end())
|
if (it != default_screen_visuals_.end())
|
||||||
return &it->second;
|
return &it->second;
|
||||||
@@ -321,6 +352,7 @@ const Connection::VisualInfo* Connection::GetVisualInfoFromId(
|
|||||||
}
|
}
|
||||||
|
|
||||||
KeyCode Connection::KeysymToKeycode(KeySym keysym) {
|
KeyCode Connection::KeysymToKeycode(KeySym keysym) {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
uint8_t min_keycode = static_cast<uint8_t>(setup_.min_keycode);
|
uint8_t min_keycode = static_cast<uint8_t>(setup_.min_keycode);
|
||||||
uint8_t max_keycode = static_cast<uint8_t>(setup_.max_keycode);
|
uint8_t max_keycode = static_cast<uint8_t>(setup_.max_keycode);
|
||||||
uint8_t count = max_keycode - min_keycode + 1;
|
uint8_t count = max_keycode - min_keycode + 1;
|
||||||
@@ -336,15 +368,23 @@ KeyCode Connection::KeysymToKeycode(KeySym keysym) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
KeySym Connection::KeycodeToKeysym(uint32_t keycode, unsigned int modifiers) {
|
KeySym Connection::KeycodeToKeysym(uint32_t keycode, unsigned int modifiers) {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
auto sym = TranslateKey(keycode, modifiers);
|
auto sym = TranslateKey(keycode, modifiers);
|
||||||
return sym == static_cast<KeySym>(XK_VoidSymbol) ? kNoSymbol : sym;
|
return sym == static_cast<KeySym>(XK_VoidSymbol) ? kNoSymbol : sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Connection> Connection::Clone() const {
|
std::unique_ptr<Connection> Connection::Clone() const {
|
||||||
return std::make_unique<Connection>(XDisplayString(display_));
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
|
return std::make_unique<Connection>(display_ ? XDisplayString(display_) : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Connection::DetachFromSequence() {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
|
DETACH_FROM_SEQUENCE(sequence_checker_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::Dispatch(Delegate* delegate) {
|
void Connection::Dispatch(Delegate* delegate) {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
DCHECK(display_);
|
DCHECK(display_);
|
||||||
|
|
||||||
auto process_next_response = [&] {
|
auto process_next_response = [&] {
|
||||||
@@ -404,6 +444,7 @@ void Connection::Dispatch(Delegate* delegate) {
|
|||||||
|
|
||||||
void Connection::AddRequest(unsigned int sequence,
|
void Connection::AddRequest(unsigned int sequence,
|
||||||
FutureBase::ResponseCallback callback) {
|
FutureBase::ResponseCallback callback) {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
DCHECK(requests_.empty() ||
|
DCHECK(requests_.empty() ||
|
||||||
CompareSequenceIds(requests_.back().sequence, sequence) < 0);
|
CompareSequenceIds(requests_.back().sequence, sequence) < 0);
|
||||||
|
|
||||||
|
@@ -9,6 +9,8 @@
|
|||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
#include "base/component_export.h"
|
#include "base/component_export.h"
|
||||||
|
#include "base/sequence_checker.h"
|
||||||
|
#include "ui/events/platform/platform_event_source.h"
|
||||||
#include "ui/gfx/x/event.h"
|
#include "ui/gfx/x/event.h"
|
||||||
#include "ui/gfx/x/extension_manager.h"
|
#include "ui/gfx/x/extension_manager.h"
|
||||||
#include "ui/gfx/x/xproto.h"
|
#include "ui/gfx/x/xproto.h"
|
||||||
@@ -33,27 +35,47 @@ class COMPONENT_EXPORT(X11) Connection : public XProto,
|
|||||||
const VisualType* visual_type;
|
const VisualType* visual_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Gets or creates the singleton connection.
|
// Gets or creates the thread local connection instance.
|
||||||
static Connection* Get();
|
static Connection* Get();
|
||||||
|
|
||||||
|
// Sets the thread local connection instance.
|
||||||
|
static void Set(std::unique_ptr<x11::Connection> connection);
|
||||||
|
|
||||||
explicit Connection(const std::string& address = "");
|
explicit Connection(const std::string& address = "");
|
||||||
~Connection();
|
~Connection();
|
||||||
|
|
||||||
Connection(const Connection&) = delete;
|
Connection(const Connection&) = delete;
|
||||||
Connection(Connection&&) = delete;
|
Connection(Connection&&) = delete;
|
||||||
|
|
||||||
XDisplay* display() const { return display_; }
|
XDisplay* display() const {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
|
return display_;
|
||||||
|
}
|
||||||
xcb_connection_t* XcbConnection();
|
xcb_connection_t* XcbConnection();
|
||||||
|
|
||||||
uint32_t extended_max_request_length() const {
|
uint32_t extended_max_request_length() const {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
return extended_max_request_length_;
|
return extended_max_request_length_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Setup& setup() const { return setup_; }
|
const Setup& setup() const {
|
||||||
const Screen& default_screen() const { return *default_screen_; }
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
x11::Window default_root() const { return default_screen().root; }
|
return setup_;
|
||||||
const Depth& default_root_depth() const { return *default_root_depth_; }
|
}
|
||||||
|
const Screen& default_screen() const {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
|
return *default_screen_;
|
||||||
|
}
|
||||||
|
x11::Window default_root() const {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
|
return default_screen().root;
|
||||||
|
}
|
||||||
|
const Depth& default_root_depth() const {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
|
return *default_root_depth_;
|
||||||
|
}
|
||||||
const VisualType& default_root_visual() const {
|
const VisualType& default_root_visual() const {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
return *default_root_visual_;
|
return *default_root_visual_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,6 +83,7 @@ class COMPONENT_EXPORT(X11) Connection : public XProto,
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T GenerateId() {
|
T GenerateId() {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
return static_cast<T>(xcb_generate_id(XcbConnection()));
|
return static_cast<T>(xcb_generate_id(XcbConnection()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,10 +114,22 @@ class COMPONENT_EXPORT(X11) Connection : public XProto,
|
|||||||
KeySym KeycodeToKeysym(uint32_t keycode, unsigned int modifiers);
|
KeySym KeycodeToKeysym(uint32_t keycode, unsigned int modifiers);
|
||||||
|
|
||||||
// Access the event buffer. Clients can add, delete, or modify events.
|
// Access the event buffer. Clients can add, delete, or modify events.
|
||||||
std::list<Event>& events() { return events_; }
|
std::list<Event>& events() {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
|
return events_;
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<Connection> Clone() const;
|
std::unique_ptr<Connection> Clone() const;
|
||||||
|
|
||||||
|
// Releases ownership of this connection to a different thread.
|
||||||
|
void DetachFromSequence();
|
||||||
|
|
||||||
|
// The viz compositor thread hangs a PlatformEventSource off the connection so
|
||||||
|
// that it gets destroyed at the appropriate time.
|
||||||
|
// TODO(thomasanderson): This is a layering violation and this should be moved
|
||||||
|
// somewhere else.
|
||||||
|
std::unique_ptr<ui::PlatformEventSource> platform_event_source;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class FutureBase;
|
friend class FutureBase;
|
||||||
|
|
||||||
@@ -142,6 +177,8 @@ class COMPONENT_EXPORT(X11) Connection : public XProto,
|
|||||||
std::list<Event> events_;
|
std::list<Event> events_;
|
||||||
|
|
||||||
std::queue<Request> requests_;
|
std::queue<Request> requests_;
|
||||||
|
|
||||||
|
SEQUENCE_CHECKER(sequence_checker_);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace x11
|
} // namespace x11
|
||||||
|
@@ -33,14 +33,12 @@ SoftwareRenderer::SoftwareRenderer(
|
|||||||
vsync_period_(
|
vsync_period_(
|
||||||
base::TimeDelta::FromMilliseconds(kFrameDelayMilliseconds)) {}
|
base::TimeDelta::FromMilliseconds(kFrameDelayMilliseconds)) {}
|
||||||
|
|
||||||
SoftwareRenderer::~SoftwareRenderer() {}
|
SoftwareRenderer::~SoftwareRenderer() = default;
|
||||||
|
|
||||||
bool SoftwareRenderer::Initialize() {
|
bool SoftwareRenderer::Initialize() {
|
||||||
software_surface_ =
|
software_surface_ = ui::OzonePlatform::GetInstance()
|
||||||
ui::OzonePlatform::GetInstance()
|
->GetSurfaceFactoryOzone()
|
||||||
->GetSurfaceFactoryOzone()
|
->CreateCanvasForWidget(widget_);
|
||||||
->CreateCanvasForWidget(widget_,
|
|
||||||
base::ThreadTaskRunnerHandle::Get().get());
|
|
||||||
if (!software_surface_) {
|
if (!software_surface_) {
|
||||||
LOG(ERROR) << "Failed to create software surface";
|
LOG(ERROR) << "Failed to create software surface";
|
||||||
return false;
|
return false;
|
||||||
|
@@ -113,8 +113,7 @@ GLOzone* SurfaceFactoryCast::GetGLOzone(gl::GLImplementation implementation) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<SurfaceOzoneCanvas> SurfaceFactoryCast::CreateCanvasForWidget(
|
std::unique_ptr<SurfaceOzoneCanvas> SurfaceFactoryCast::CreateCanvasForWidget(
|
||||||
gfx::AcceleratedWidget widget,
|
gfx::AcceleratedWidget widget) {
|
||||||
scoped_refptr<base::SequencedTaskRunner> task_runner) {
|
|
||||||
// Software canvas support only in headless mode
|
// Software canvas support only in headless mode
|
||||||
if (egl_implementation_)
|
if (egl_implementation_)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@@ -32,8 +32,7 @@ class SurfaceFactoryCast : public SurfaceFactoryOzone {
|
|||||||
std::vector<gl::GLImplementation> GetAllowedGLImplementations() override;
|
std::vector<gl::GLImplementation> GetAllowedGLImplementations() override;
|
||||||
GLOzone* GetGLOzone(gl::GLImplementation implementation) override;
|
GLOzone* GetGLOzone(gl::GLImplementation implementation) override;
|
||||||
std::unique_ptr<SurfaceOzoneCanvas> CreateCanvasForWidget(
|
std::unique_ptr<SurfaceOzoneCanvas> CreateCanvasForWidget(
|
||||||
gfx::AcceleratedWidget widget,
|
gfx::AcceleratedWidget widget) override;
|
||||||
scoped_refptr<base::SequencedTaskRunner> task_runner) override;
|
|
||||||
scoped_refptr<gfx::NativePixmap> CreateNativePixmap(
|
scoped_refptr<gfx::NativePixmap> CreateNativePixmap(
|
||||||
gfx::AcceleratedWidget widget,
|
gfx::AcceleratedWidget widget,
|
||||||
VkDevice vk_device,
|
VkDevice vk_device,
|
||||||
|
@@ -350,8 +350,7 @@ std::unique_ptr<OverlaySurface> GbmSurfaceFactory::CreateOverlaySurface(
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<SurfaceOzoneCanvas> GbmSurfaceFactory::CreateCanvasForWidget(
|
std::unique_ptr<SurfaceOzoneCanvas> GbmSurfaceFactory::CreateCanvasForWidget(
|
||||||
gfx::AcceleratedWidget widget,
|
gfx::AcceleratedWidget widget) {
|
||||||
scoped_refptr<base::SequencedTaskRunner> task_runner) {
|
|
||||||
DCHECK(thread_checker_.CalledOnValidThread());
|
DCHECK(thread_checker_.CalledOnValidThread());
|
||||||
LOG(ERROR) << "Software rendering mode is not supported with GBM platform";
|
LOG(ERROR) << "Software rendering mode is not supported with GBM platform";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@@ -54,8 +54,7 @@ class GbmSurfaceFactory : public SurfaceFactoryOzone {
|
|||||||
std::unique_ptr<OverlaySurface> CreateOverlaySurface(
|
std::unique_ptr<OverlaySurface> CreateOverlaySurface(
|
||||||
gfx::AcceleratedWidget window) override;
|
gfx::AcceleratedWidget window) override;
|
||||||
std::unique_ptr<SurfaceOzoneCanvas> CreateCanvasForWidget(
|
std::unique_ptr<SurfaceOzoneCanvas> CreateCanvasForWidget(
|
||||||
gfx::AcceleratedWidget widget,
|
gfx::AcceleratedWidget widget) override;
|
||||||
scoped_refptr<base::SequencedTaskRunner> task_runner) override;
|
|
||||||
scoped_refptr<gfx::NativePixmap> CreateNativePixmap(
|
scoped_refptr<gfx::NativePixmap> CreateNativePixmap(
|
||||||
gfx::AcceleratedWidget widget,
|
gfx::AcceleratedWidget widget,
|
||||||
VkDevice vk_device,
|
VkDevice vk_device,
|
||||||
|
@@ -234,9 +234,7 @@ GLOzone* HeadlessSurfaceFactory::GetGLOzone(
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<SurfaceOzoneCanvas>
|
std::unique_ptr<SurfaceOzoneCanvas>
|
||||||
HeadlessSurfaceFactory::CreateCanvasForWidget(
|
HeadlessSurfaceFactory::CreateCanvasForWidget(gfx::AcceleratedWidget widget) {
|
||||||
gfx::AcceleratedWidget widget,
|
|
||||||
scoped_refptr<base::SequencedTaskRunner> task_runner) {
|
|
||||||
return std::make_unique<FileSurface>(GetPathForWidget(base_path_, widget));
|
return std::make_unique<FileSurface>(GetPathForWidget(base_path_, widget));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -24,8 +24,7 @@ class HeadlessSurfaceFactory : public SurfaceFactoryOzone {
|
|||||||
std::vector<gl::GLImplementation> GetAllowedGLImplementations() override;
|
std::vector<gl::GLImplementation> GetAllowedGLImplementations() override;
|
||||||
GLOzone* GetGLOzone(gl::GLImplementation implementation) override;
|
GLOzone* GetGLOzone(gl::GLImplementation implementation) override;
|
||||||
std::unique_ptr<SurfaceOzoneCanvas> CreateCanvasForWidget(
|
std::unique_ptr<SurfaceOzoneCanvas> CreateCanvasForWidget(
|
||||||
gfx::AcceleratedWidget widget,
|
gfx::AcceleratedWidget widget) override;
|
||||||
scoped_refptr<base::SequencedTaskRunner> task_runner) override;
|
|
||||||
scoped_refptr<gfx::NativePixmap> CreateNativePixmap(
|
scoped_refptr<gfx::NativePixmap> CreateNativePixmap(
|
||||||
gfx::AcceleratedWidget widget,
|
gfx::AcceleratedWidget widget,
|
||||||
VkDevice vk_device,
|
VkDevice vk_device,
|
||||||
|
@@ -44,11 +44,11 @@ namespace ui {
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr OzonePlatform::PlatformProperties kScenicPlatformProperties{
|
constexpr OzonePlatform::PlatformProperties kScenicPlatformProperties{
|
||||||
/*needs_view_token=*/true,
|
.needs_view_token = true,
|
||||||
/*custom_frame_pref_default=*/false,
|
.custom_frame_pref_default = false,
|
||||||
/*use_system_title_bar=*/false,
|
.use_system_title_bar = false,
|
||||||
/*message_pump_type_for_gpu=*/base::MessagePumpType::IO,
|
.message_pump_type_for_gpu = base::MessagePumpType::IO,
|
||||||
/*supports_vulkan_swap_chain=*/true,
|
.supports_vulkan_swap_chain = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
class ScenicPlatformEventSource : public ui::PlatformEventSource {
|
class ScenicPlatformEventSource : public ui::PlatformEventSource {
|
||||||
|
@@ -207,8 +207,7 @@ ScenicSurfaceFactory::CreatePlatformWindowSurface(
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<SurfaceOzoneCanvas> ScenicSurfaceFactory::CreateCanvasForWidget(
|
std::unique_ptr<SurfaceOzoneCanvas> ScenicSurfaceFactory::CreateCanvasForWidget(
|
||||||
gfx::AcceleratedWidget widget,
|
gfx::AcceleratedWidget widget) {
|
||||||
scoped_refptr<base::SequencedTaskRunner> task_runner) {
|
|
||||||
ScenicSurface* surface = GetSurface(widget);
|
ScenicSurface* surface = GetSurface(widget);
|
||||||
return std::make_unique<ScenicWindowCanvas>(surface);
|
return std::make_unique<ScenicWindowCanvas>(surface);
|
||||||
}
|
}
|
||||||
|
@@ -47,8 +47,7 @@ class ScenicSurfaceFactory : public SurfaceFactoryOzone {
|
|||||||
std::unique_ptr<PlatformWindowSurface> CreatePlatformWindowSurface(
|
std::unique_ptr<PlatformWindowSurface> CreatePlatformWindowSurface(
|
||||||
gfx::AcceleratedWidget widget) override;
|
gfx::AcceleratedWidget widget) override;
|
||||||
std::unique_ptr<SurfaceOzoneCanvas> CreateCanvasForWidget(
|
std::unique_ptr<SurfaceOzoneCanvas> CreateCanvasForWidget(
|
||||||
gfx::AcceleratedWidget widget,
|
gfx::AcceleratedWidget widget) override;
|
||||||
scoped_refptr<base::SequencedTaskRunner> task_runner) override;
|
|
||||||
scoped_refptr<gfx::NativePixmap> CreateNativePixmap(
|
scoped_refptr<gfx::NativePixmap> CreateNativePixmap(
|
||||||
gfx::AcceleratedWidget widget,
|
gfx::AcceleratedWidget widget,
|
||||||
VkDevice vk_device,
|
VkDevice vk_device,
|
||||||
|
@@ -136,9 +136,7 @@ WaylandSurfaceFactory::WaylandSurfaceFactory(
|
|||||||
WaylandSurfaceFactory::~WaylandSurfaceFactory() = default;
|
WaylandSurfaceFactory::~WaylandSurfaceFactory() = default;
|
||||||
|
|
||||||
std::unique_ptr<SurfaceOzoneCanvas>
|
std::unique_ptr<SurfaceOzoneCanvas>
|
||||||
WaylandSurfaceFactory::CreateCanvasForWidget(
|
WaylandSurfaceFactory::CreateCanvasForWidget(gfx::AcceleratedWidget widget) {
|
||||||
gfx::AcceleratedWidget widget,
|
|
||||||
scoped_refptr<base::SequencedTaskRunner> task_runner) {
|
|
||||||
return std::make_unique<WaylandCanvasSurface>(buffer_manager_, widget);
|
return std::make_unique<WaylandCanvasSurface>(buffer_manager_, widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -35,8 +35,7 @@ class WaylandSurfaceFactory : public SurfaceFactoryOzone {
|
|||||||
bool enforce_protected_memory) override;
|
bool enforce_protected_memory) override;
|
||||||
#endif
|
#endif
|
||||||
std::unique_ptr<SurfaceOzoneCanvas> CreateCanvasForWidget(
|
std::unique_ptr<SurfaceOzoneCanvas> CreateCanvasForWidget(
|
||||||
gfx::AcceleratedWidget widget,
|
gfx::AcceleratedWidget widget) override;
|
||||||
scoped_refptr<base::SequencedTaskRunner> task_runner) override;
|
|
||||||
scoped_refptr<gfx::NativePixmap> CreateNativePixmap(
|
scoped_refptr<gfx::NativePixmap> CreateNativePixmap(
|
||||||
gfx::AcceleratedWidget widget,
|
gfx::AcceleratedWidget widget,
|
||||||
VkDevice vk_device,
|
VkDevice vk_device,
|
||||||
|
@@ -185,8 +185,7 @@ class WaylandSurfaceFactoryTest : public WaylandTest {
|
|||||||
protected:
|
protected:
|
||||||
std::unique_ptr<SurfaceOzoneCanvas> CreateCanvas(
|
std::unique_ptr<SurfaceOzoneCanvas> CreateCanvas(
|
||||||
gfx::AcceleratedWidget widget) {
|
gfx::AcceleratedWidget widget) {
|
||||||
auto canvas = surface_factory_->CreateCanvasForWidget(
|
auto canvas = surface_factory_->CreateCanvasForWidget(widget_);
|
||||||
widget_, base::ThreadTaskRunnerHandle::Get().get());
|
|
||||||
base::RunLoop().RunUntilIdle();
|
base::RunLoop().RunUntilIdle();
|
||||||
|
|
||||||
return canvas;
|
return canvas;
|
||||||
|
@@ -72,6 +72,9 @@ constexpr OzonePlatform::PlatformProperties kX11PlatformProperties{
|
|||||||
// When the Ozone X11 backend is running, use a UI loop to grab Expose
|
// When the Ozone X11 backend is running, use a UI loop to grab Expose
|
||||||
// events. See GLSurfaceGLX and https://crbug.com/326995.
|
// events. See GLSurfaceGLX and https://crbug.com/326995.
|
||||||
.message_pump_type_for_gpu = base::MessagePumpType::UI,
|
.message_pump_type_for_gpu = base::MessagePumpType::UI,
|
||||||
|
// When the Ozone X11 backend is running, use a UI loop to dispatch
|
||||||
|
// SHM completion events.
|
||||||
|
.message_pump_type_for_viz_compositor = base::MessagePumpType::UI,
|
||||||
.supports_vulkan_swap_chain = true,
|
.supports_vulkan_swap_chain = true,
|
||||||
.platform_shows_drag_image = false,
|
.platform_shows_drag_image = false,
|
||||||
.supports_global_application_menus = true};
|
.supports_global_application_menus = true};
|
||||||
@@ -205,7 +208,12 @@ class OzonePlatformX11 : public OzonePlatform,
|
|||||||
if (!params.single_process)
|
if (!params.single_process)
|
||||||
CreatePlatformEventSource();
|
CreatePlatformEventSource();
|
||||||
|
|
||||||
surface_factory_ozone_ = std::make_unique<X11SurfaceFactory>();
|
// Set up the X11 connection before the sandbox gets set up. This cannot be
|
||||||
|
// done later since opening the connection requires socket() and connect().
|
||||||
|
auto connection = x11::Connection::Get()->Clone();
|
||||||
|
connection->DetachFromSequence();
|
||||||
|
surface_factory_ozone_ =
|
||||||
|
std::make_unique<X11SurfaceFactory>(std::move(connection));
|
||||||
gl_egl_utility_ = std::make_unique<GLEGLUtilityX11>();
|
gl_egl_utility_ = std::make_unique<GLEGLUtilityX11>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -11,13 +11,8 @@
|
|||||||
|
|
||||||
namespace ui {
|
namespace ui {
|
||||||
|
|
||||||
X11CanvasSurface::X11CanvasSurface(
|
X11CanvasSurface::X11CanvasSurface(gfx::AcceleratedWidget widget)
|
||||||
gfx::AcceleratedWidget widget,
|
: x11_software_bitmap_presenter_(widget) {}
|
||||||
scoped_refptr<base::SequencedTaskRunner> gpu_task_runner)
|
|
||||||
: task_runner_(base::SequencedTaskRunnerHandle::Get()),
|
|
||||||
x11_software_bitmap_presenter_(widget,
|
|
||||||
task_runner_.get(),
|
|
||||||
std::move(gpu_task_runner)) {}
|
|
||||||
|
|
||||||
X11CanvasSurface::~X11CanvasSurface() = default;
|
X11CanvasSurface::~X11CanvasSurface() = default;
|
||||||
|
|
||||||
|
@@ -28,8 +28,7 @@ namespace ui {
|
|||||||
// the software output is destroyed.
|
// the software output is destroyed.
|
||||||
class X11CanvasSurface : public SurfaceOzoneCanvas {
|
class X11CanvasSurface : public SurfaceOzoneCanvas {
|
||||||
public:
|
public:
|
||||||
X11CanvasSurface(gfx::AcceleratedWidget widget,
|
explicit X11CanvasSurface(gfx::AcceleratedWidget widget);
|
||||||
scoped_refptr<base::SequencedTaskRunner> gpu_task_runner);
|
|
||||||
~X11CanvasSurface() override;
|
~X11CanvasSurface() override;
|
||||||
|
|
||||||
// SurfaceOzoneCanvas overrides:
|
// SurfaceOzoneCanvas overrides:
|
||||||
@@ -45,8 +44,6 @@ class X11CanvasSurface : public SurfaceOzoneCanvas {
|
|||||||
// Current surface we paint to.
|
// Current surface we paint to.
|
||||||
sk_sp<SkSurface> surface_;
|
sk_sp<SkSurface> surface_;
|
||||||
|
|
||||||
scoped_refptr<base::SequencedTaskRunner> task_runner_;
|
|
||||||
|
|
||||||
// Helper X11 bitmap presenter that presents the contents.
|
// Helper X11 bitmap presenter that presents the contents.
|
||||||
X11SoftwareBitmapPresenter x11_software_bitmap_presenter_;
|
X11SoftwareBitmapPresenter x11_software_bitmap_presenter_;
|
||||||
|
|
||||||
|
@@ -7,6 +7,8 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "gpu/vulkan/buildflags.h"
|
#include "gpu/vulkan/buildflags.h"
|
||||||
|
#include "ui/events/platform/x11/x11_event_source.h"
|
||||||
|
#include "ui/gfx/x/connection.h"
|
||||||
#include "ui/gfx/x/x11.h"
|
#include "ui/gfx/x/x11.h"
|
||||||
#include "ui/gfx/x/x11_types.h"
|
#include "ui/gfx/x/x11_types.h"
|
||||||
#include "ui/gl/gl_surface_egl.h"
|
#include "ui/gl/gl_surface_egl.h"
|
||||||
@@ -73,11 +75,13 @@ class GLOzoneEGLX11 : public GLOzoneEGL {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
X11SurfaceFactory::X11SurfaceFactory()
|
X11SurfaceFactory::X11SurfaceFactory(
|
||||||
|
std::unique_ptr<x11::Connection> connection)
|
||||||
: glx_implementation_(std::make_unique<GLOzoneGLX>()),
|
: glx_implementation_(std::make_unique<GLOzoneGLX>()),
|
||||||
egl_implementation_(std::make_unique<GLOzoneEGLX11>()) {}
|
egl_implementation_(std::make_unique<GLOzoneEGLX11>()),
|
||||||
|
connection_(std::move(connection)) {}
|
||||||
|
|
||||||
X11SurfaceFactory::~X11SurfaceFactory() {}
|
X11SurfaceFactory::~X11SurfaceFactory() = default;
|
||||||
|
|
||||||
std::vector<gl::GLImplementation>
|
std::vector<gl::GLImplementation>
|
||||||
X11SurfaceFactory::GetAllowedGLImplementations() {
|
X11SurfaceFactory::GetAllowedGLImplementations() {
|
||||||
@@ -107,9 +111,16 @@ X11SurfaceFactory::CreateVulkanImplementation(bool allow_protected_memory,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::unique_ptr<SurfaceOzoneCanvas> X11SurfaceFactory::CreateCanvasForWidget(
|
std::unique_ptr<SurfaceOzoneCanvas> X11SurfaceFactory::CreateCanvasForWidget(
|
||||||
gfx::AcceleratedWidget widget,
|
gfx::AcceleratedWidget widget) {
|
||||||
scoped_refptr<base::SequencedTaskRunner> task_runner) {
|
// X11SoftwareBitmapPresenter (created via X11CanvasSurface) requres a
|
||||||
return std::make_unique<X11CanvasSurface>(widget, std::move(task_runner));
|
// Connection TLS instance and a PlatformEventSource.
|
||||||
|
if (connection_) {
|
||||||
|
auto* connection = connection_.get();
|
||||||
|
x11::Connection::Set(std::move(connection_));
|
||||||
|
connection->platform_event_source =
|
||||||
|
std::make_unique<X11EventSource>(connection);
|
||||||
|
}
|
||||||
|
return std::make_unique<X11CanvasSurface>(widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ui
|
} // namespace ui
|
||||||
|
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include "base/macros.h"
|
#include "base/macros.h"
|
||||||
#include "gpu/vulkan/buildflags.h"
|
#include "gpu/vulkan/buildflags.h"
|
||||||
|
#include "ui/gfx/x/connection.h"
|
||||||
#include "ui/gl/gl_surface.h"
|
#include "ui/gl/gl_surface.h"
|
||||||
#include "ui/ozone/public/gl_ozone.h"
|
#include "ui/ozone/public/gl_ozone.h"
|
||||||
#include "ui/ozone/public/surface_factory_ozone.h"
|
#include "ui/ozone/public/surface_factory_ozone.h"
|
||||||
@@ -19,7 +20,7 @@ namespace ui {
|
|||||||
// Handles GL initialization and surface/context creation for X11.
|
// Handles GL initialization and surface/context creation for X11.
|
||||||
class X11SurfaceFactory : public SurfaceFactoryOzone {
|
class X11SurfaceFactory : public SurfaceFactoryOzone {
|
||||||
public:
|
public:
|
||||||
X11SurfaceFactory();
|
explicit X11SurfaceFactory(std::unique_ptr<x11::Connection> connection);
|
||||||
~X11SurfaceFactory() override;
|
~X11SurfaceFactory() override;
|
||||||
|
|
||||||
// SurfaceFactoryOzone:
|
// SurfaceFactoryOzone:
|
||||||
@@ -31,13 +32,14 @@ class X11SurfaceFactory : public SurfaceFactoryOzone {
|
|||||||
bool enforce_protected_memory) override;
|
bool enforce_protected_memory) override;
|
||||||
#endif
|
#endif
|
||||||
std::unique_ptr<SurfaceOzoneCanvas> CreateCanvasForWidget(
|
std::unique_ptr<SurfaceOzoneCanvas> CreateCanvasForWidget(
|
||||||
gfx::AcceleratedWidget widget,
|
gfx::AcceleratedWidget widget) override;
|
||||||
scoped_refptr<base::SequencedTaskRunner> task_runner) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<GLOzone> glx_implementation_;
|
std::unique_ptr<GLOzone> glx_implementation_;
|
||||||
std::unique_ptr<GLOzone> egl_implementation_;
|
std::unique_ptr<GLOzone> egl_implementation_;
|
||||||
|
|
||||||
|
std::unique_ptr<x11::Connection> connection_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(X11SurfaceFactory);
|
DISALLOW_COPY_AND_ASSIGN(X11SurfaceFactory);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -87,6 +87,11 @@ class COMPONENT_EXPORT(OZONE) OzonePlatform {
|
|||||||
base::MessagePumpType message_pump_type_for_gpu =
|
base::MessagePumpType message_pump_type_for_gpu =
|
||||||
base::MessagePumpType::DEFAULT;
|
base::MessagePumpType::DEFAULT;
|
||||||
|
|
||||||
|
// Determines the type of message pump that should be used for viz
|
||||||
|
// compositor thread.
|
||||||
|
base::MessagePumpType message_pump_type_for_viz_compositor =
|
||||||
|
base::MessagePumpType::DEFAULT;
|
||||||
|
|
||||||
// Determines if the platform supports vulkan swap chain.
|
// Determines if the platform supports vulkan swap chain.
|
||||||
bool supports_vulkan_swap_chain = false;
|
bool supports_vulkan_swap_chain = false;
|
||||||
|
|
||||||
|
@@ -66,8 +66,7 @@ std::unique_ptr<OverlaySurface> SurfaceFactoryOzone::CreateOverlaySurface(
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<SurfaceOzoneCanvas> SurfaceFactoryOzone::CreateCanvasForWidget(
|
std::unique_ptr<SurfaceOzoneCanvas> SurfaceFactoryOzone::CreateCanvasForWidget(
|
||||||
gfx::AcceleratedWidget widget,
|
gfx::AcceleratedWidget widget) {
|
||||||
scoped_refptr<base::SequencedTaskRunner> task_runner) {
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -108,14 +108,12 @@ class COMPONENT_EXPORT(OZONE_BASE) SurfaceFactoryOzone {
|
|||||||
virtual std::unique_ptr<OverlaySurface> CreateOverlaySurface(
|
virtual std::unique_ptr<OverlaySurface> CreateOverlaySurface(
|
||||||
gfx::AcceleratedWidget window);
|
gfx::AcceleratedWidget window);
|
||||||
|
|
||||||
// Create SurfaceOzoneCanvas for the specified gfx::AcceleratedWidget. The
|
// Create SurfaceOzoneCanvas for the specified gfx::AcceleratedWidget.
|
||||||
// |task_runner| may be null if the gpu service runs in a host process.
|
|
||||||
//
|
//
|
||||||
// Note: The platform must support creation of SurfaceOzoneCanvas from the
|
// Note: The platform must support creation of SurfaceOzoneCanvas from the
|
||||||
// Browser Process using only the handle contained in gfx::AcceleratedWidget.
|
// Browser Process using only the handle contained in gfx::AcceleratedWidget.
|
||||||
virtual std::unique_ptr<SurfaceOzoneCanvas> CreateCanvasForWidget(
|
virtual std::unique_ptr<SurfaceOzoneCanvas> CreateCanvasForWidget(
|
||||||
gfx::AcceleratedWidget widget,
|
gfx::AcceleratedWidget widget);
|
||||||
scoped_refptr<base::SequencedTaskRunner> task_runner);
|
|
||||||
|
|
||||||
// Create a single native buffer to be used for overlay planes or zero copy
|
// Create a single native buffer to be used for overlay planes or zero copy
|
||||||
// for |widget| representing a particular display controller or default
|
// for |widget| representing a particular display controller or default
|
||||||
|
Reference in New Issue
Block a user