1 // Copyright 2013 Intel Corporation. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ozone/impl/ozone_display.h"
8 #include "content/child/child_process.h"
9 #include "ozone/impl/desktop_screen_wayland.h"
10 #include "ozone/impl/ipc/display_channel.h"
11 #include "ozone/impl/ipc/display_channel_host.h"
12 #include "ozone/ui/events/event_converter_in_process.h"
13 #include "ozone/ui/events/remote_event_dispatcher.h"
14 #include "ozone/wayland/display.h"
15 #include "ozone/wayland/screen.h"
16 #include "ozone/wayland/window.h"
18 namespace ozonewayland {
20 OzoneDisplay* OzoneDisplay::instance_ = NULL;
22 OzoneDisplay* OzoneDisplay::GetInstance() {
26 OzoneDisplay::OzoneDisplay() : desktop_screen_(NULL),
30 event_converter_(NULL) {
34 OzoneDisplay::~OzoneDisplay() {
39 bool OzoneDisplay::InitializeHardware() {
40 display_ = new WaylandDisplay(WaylandDisplay::RegisterAsNeeded);
41 bool initialized_hardware = display_->display() ? true : false;
42 if (initialized_hardware && !content::ChildProcess::current()) {
43 // In the multi-process mode, DisplayChannel (in GPU process side) is in
44 // charge of establishing an IPC channel with DisplayChannelHost (in
45 // Browser Process side). At this moment the GPU process is still
46 // initializing though, so DisplayChannel cannot establish the connection
47 // and need to delay this to later. Therefore post a task to GpuChildThread
48 // and let DisplayChannel handle this right after the GPU process is
50 base::MessageLoop::current()->message_loop_proxy()->PostTask(
51 FROM_HERE, base::Bind(&OzoneDisplay::DelayedInitialization, this));
54 return initialized_hardware;
57 void OzoneDisplay::ShutdownHardware() {
61 intptr_t OzoneDisplay::GetNativeDisplay() {
62 return (intptr_t)display_->display();
65 gfx::Screen* OzoneDisplay::CreateDesktopScreen() {
66 if (!desktop_screen_) {
67 desktop_screen_ = new views::DesktopScreenWayland;
68 LookAheadOutputGeometry();
71 return desktop_screen_;
74 const views::DesktopScreenWayland* OzoneDisplay::GetPrimaryScreen() const {
75 // TODO(kalyan): For now always return DesktopScreen. Needs proper fixing
76 // after multi screen support is added.
77 return desktop_screen_;
80 gfx::AcceleratedWidget OzoneDisplay::GetAcceleratedWidget() {
81 static int opaque_handle = 0;
82 // Ensure Event Converter is initialized.
83 if (!event_converter_) {
84 event_converter_ = new EventConverterInProcess();
85 event_converter_->SetOutputChangeObserver(this);
88 display_->StartProcessingEvents();
91 host_ = new OzoneDisplayChannelHost();
96 WindowStateChangeHandler::GetInstance()->SetWidgetState(opaque_handle,
101 return (gfx::AcceleratedWidget)opaque_handle;
104 gfx::AcceleratedWidget OzoneDisplay::RealizeAcceleratedWidget(
105 gfx::AcceleratedWidget w) {
107 // Event Converter should be already initialized unless we are in gpu process
109 if (!event_converter_) {
110 event_converter_ = new RemoteEventDispatcher();
111 display_->StartProcessingEvents();
114 WaylandWindow* widget = GetWidget(w);
116 widget->RealizeAcceleratedWidget();
117 return (gfx::AcceleratedWidget)widget->egl_window();
120 void OzoneDisplay::OnOutputSizeChanged(unsigned width, unsigned height) {
122 desktop_screen_->SetGeometry(gfx::Rect(0, 0, width, height));
125 void OzoneDisplay::DelayedInitialization(OzoneDisplay* display) {
126 display->channel_ = new OzoneDisplayChannel();
127 display->channel_->Register();
130 WaylandWindow* OzoneDisplay::GetWidget(gfx::AcceleratedWidget w) {
131 const std::map<unsigned, WaylandWindow*> widget_map =
132 display_->GetWindowList();
134 std::map<unsigned, WaylandWindow*>::const_iterator it = widget_map.find(w);
135 return it == widget_map.end() ? NULL : it->second;
138 void OzoneDisplay::Terminate() {
139 if (!event_converter_ && !desktop_screen_)
143 if (desktop_screen_) {
144 delete desktop_screen_;
145 desktop_screen_ = NULL;
149 if (event_converter_) {
150 delete event_converter_;
151 event_converter_ = NULL;
155 // TODO(vignatti): GPU process conceptually is the one that deals with hardware
156 // details and therefore we assume that the window system connection should
157 // happen in there only. There's a glitch with Chrome though, that creates its
158 // frame contents requiring access to the window system, before the GPU process
159 // even exists. In other words, Chrome runs
160 // BrowserMainLoop::PreMainMessageLoopRun before GpuProcessHost::Get. If the
161 // assumption of window system connection belongs to the GPU process is valid,
162 // then I believe this Chrome behavior needs to be addressed upstream.
164 // For now, we create another window system connection to look ahead the needed
165 // output properties that Chrome (among others) need and then close right after
166 // that. I haven't measured how long it takes to open a Wayland connection,
167 // listen all the interface the compositor sends and close it, but _for_ _sure_
168 // it slows down the overall initialization time of Chromium targets.
169 // Therefore, this is something that has to be solved in the future, moving all
170 // Chrome tasks after GPU process is created.
172 void OzoneDisplay::LookAheadOutputGeometry() {
173 DCHECK(desktop_screen_);
174 WaylandDisplay disp_(WaylandDisplay::RegisterOutputOnly);
175 CHECK(disp_.display()) << "Ozone: Wayland server connection not found.";
177 while (disp_.PrimaryScreen()->Geometry().IsEmpty())
180 desktop_screen_->SetGeometry(disp_.PrimaryScreen()->Geometry());
183 } // namespace ozonewayland