Upstream version 6.34.113.0
[platform/framework/web/crosswalk.git] / src / ozone / impl / ozone_display.cc
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.
4
5 #include "ozone/impl/ozone_display.h"
6
7 #include <map>
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"
17
18 namespace ozonewayland {
19
20 OzoneDisplay* OzoneDisplay::instance_ = NULL;
21
22 OzoneDisplay* OzoneDisplay::GetInstance() {
23   return instance_;
24 }
25
26 OzoneDisplay::OzoneDisplay() : desktop_screen_(NULL),
27     display_(NULL),
28     channel_(NULL),
29     host_(NULL),
30     event_converter_(NULL) {
31   instance_ = this;
32 }
33
34 OzoneDisplay::~OzoneDisplay() {
35   Terminate();
36   instance_ = NULL;
37 }
38
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
49     // initialized.
50     base::MessageLoop::current()->message_loop_proxy()->PostTask(
51         FROM_HERE, base::Bind(&OzoneDisplay::DelayedInitialization, this));
52   }
53
54   return initialized_hardware;
55 }
56
57 void OzoneDisplay::ShutdownHardware() {
58   Terminate();
59 }
60
61 intptr_t OzoneDisplay::GetNativeDisplay() {
62   return (intptr_t)display_->display();
63 }
64
65 gfx::Screen* OzoneDisplay::CreateDesktopScreen() {
66   if (!desktop_screen_) {
67     desktop_screen_ = new views::DesktopScreenWayland;
68     LookAheadOutputGeometry();
69   }
70
71   return desktop_screen_;
72 }
73
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_;
78 }
79
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);
86
87     if (display_) {
88       display_->StartProcessingEvents();
89     } else {
90       DCHECK(!host_);
91       host_ = new OzoneDisplayChannelHost();
92     }
93   }
94
95   opaque_handle++;
96   WindowStateChangeHandler::GetInstance()->SetWidgetState(opaque_handle,
97                                                           CREATE,
98                                                           0,
99                                                           0);
100
101   return (gfx::AcceleratedWidget)opaque_handle;
102 }
103
104 gfx::AcceleratedWidget OzoneDisplay::RealizeAcceleratedWidget(
105     gfx::AcceleratedWidget w) {
106   DCHECK(display_);
107   // Event Converter should be already initialized unless we are in gpu process
108   // side.
109   if (!event_converter_) {
110     event_converter_ = new RemoteEventDispatcher();
111     display_->StartProcessingEvents();
112   }
113
114   WaylandWindow* widget = GetWidget(w);
115   DCHECK(widget);
116   widget->RealizeAcceleratedWidget();
117   return (gfx::AcceleratedWidget)widget->egl_window();
118 }
119
120 void OzoneDisplay::OnOutputSizeChanged(unsigned width, unsigned height) {
121   if (desktop_screen_)
122     desktop_screen_->SetGeometry(gfx::Rect(0, 0, width, height));
123 }
124
125 void OzoneDisplay::DelayedInitialization(OzoneDisplay* display) {
126   display->channel_ = new OzoneDisplayChannel();
127   display->channel_->Register();
128 }
129
130 WaylandWindow* OzoneDisplay::GetWidget(gfx::AcceleratedWidget w) {
131   const std::map<unsigned, WaylandWindow*> widget_map =
132       display_->GetWindowList();
133
134   std::map<unsigned, WaylandWindow*>::const_iterator it = widget_map.find(w);
135     return it == widget_map.end() ? NULL : it->second;
136 }
137
138 void OzoneDisplay::Terminate() {
139   if (!event_converter_ && !desktop_screen_)
140     return;
141
142   delete channel_;
143   if (desktop_screen_) {
144     delete desktop_screen_;
145     desktop_screen_ = NULL;
146   }
147
148   delete display_;
149   if (event_converter_) {
150     delete event_converter_;
151     event_converter_ = NULL;
152   }
153 }
154
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.
163 //
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.
171 //
172 void OzoneDisplay::LookAheadOutputGeometry() {
173   DCHECK(desktop_screen_);
174   WaylandDisplay disp_(WaylandDisplay::RegisterOutputOnly);
175   CHECK(disp_.display()) << "Ozone: Wayland server connection not found.";
176
177   while (disp_.PrimaryScreen()->Geometry().IsEmpty())
178     disp_.SyncDisplay();
179
180   desktop_screen_->SetGeometry(disp_.PrimaryScreen()->Geometry());
181 }
182
183 }  // namespace ozonewayland