OLD | NEW |
| (Empty) |
1 // Copyright 2014 The Chromium Authors. 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 "ui/ozone/platform/egltest/ozone_platform_egltest.h" | |
6 | |
7 #include <stdint.h> | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/command_line.h" | |
11 #include "base/environment.h" | |
12 #include "base/files/file_path.h" | |
13 #include "base/macros.h" | |
14 #include "base/memory/ptr_util.h" | |
15 #include "base/path_service.h" | |
16 #include "base/threading/thread_checker.h" | |
17 #include "library_loaders/libeglplatform_shim.h" | |
18 #include "third_party/khronos/EGL/egl.h" | |
19 #include "ui/events/devices/device_data_manager.h" | |
20 #include "ui/events/event.h" | |
21 #include "ui/events/ozone/device/device_manager.h" | |
22 #include "ui/events/ozone/evdev/event_factory_evdev.h" | |
23 #include "ui/events/ozone/events_ozone.h" | |
24 #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h" | |
25 #include "ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h" | |
26 #include "ui/events/platform/platform_event_dispatcher.h" | |
27 #include "ui/gfx/vsync_provider.h" | |
28 #include "ui/ozone/common/egl_util.h" | |
29 #include "ui/ozone/common/native_display_delegate_ozone.h" | |
30 #include "ui/ozone/common/stub_overlay_manager.h" | |
31 #include "ui/ozone/public/cursor_factory_ozone.h" | |
32 #include "ui/ozone/public/gpu_platform_support.h" | |
33 #include "ui/ozone/public/gpu_platform_support_host.h" | |
34 #include "ui/ozone/public/ozone_platform.h" | |
35 #include "ui/ozone/public/ozone_switches.h" | |
36 #include "ui/ozone/public/surface_factory_ozone.h" | |
37 #include "ui/ozone/public/surface_ozone_egl.h" | |
38 #include "ui/ozone/public/system_input_injector.h" | |
39 #include "ui/platform_window/platform_window.h" | |
40 #include "ui/platform_window/platform_window_delegate.h" | |
41 | |
42 namespace ui { | |
43 | |
44 namespace { | |
45 | |
46 const char kEglplatformShim[] = "EGLPLATFORM_SHIM"; | |
47 const char kEglplatformShimDefault[] = "libeglplatform_shim.so.1"; | |
48 const char kDefaultEglSoname[] = "libEGL.so.1"; | |
49 const char kDefaultGlesSoname[] = "libGLESv2.so.2"; | |
50 | |
51 // Get the library soname to load. | |
52 std::string GetShimLibraryName() { | |
53 std::string library; | |
54 std::unique_ptr<base::Environment> env(base::Environment::Create()); | |
55 if (env->GetVar(kEglplatformShim, &library)) | |
56 return library; | |
57 return kEglplatformShimDefault; | |
58 } | |
59 | |
60 // Touch events are reported in device coordinates. This scales the event to the | |
61 // window's coordinate space. | |
62 void ScaleTouchEvent(TouchEvent* event, const gfx::SizeF& size) { | |
63 for (const auto& device : | |
64 DeviceDataManager::GetInstance()->GetTouchscreenDevices()) { | |
65 if (device.id == event->source_device_id()) { | |
66 gfx::SizeF touchscreen_size = gfx::SizeF(device.size); | |
67 gfx::Transform transform; | |
68 transform.Scale(size.width() / touchscreen_size.width(), | |
69 size.height() / touchscreen_size.height()); | |
70 event->UpdateForRootTransform(transform); | |
71 return; | |
72 } | |
73 } | |
74 } | |
75 | |
76 class EgltestWindow : public PlatformWindow, public PlatformEventDispatcher { | |
77 public: | |
78 EgltestWindow(PlatformWindowDelegate* delegate, | |
79 LibeglplatformShimLoader* eglplatform_shim, | |
80 EventFactoryEvdev* event_factory, | |
81 const gfx::Rect& bounds); | |
82 ~EgltestWindow() override; | |
83 | |
84 // PlatformWindow: | |
85 gfx::Rect GetBounds() override; | |
86 void SetBounds(const gfx::Rect& bounds) override; | |
87 void SetTitle(const base::string16& title) override; | |
88 void Show() override; | |
89 void Hide() override; | |
90 void Close() override; | |
91 void SetCapture() override; | |
92 void ReleaseCapture() override; | |
93 void ToggleFullscreen() override; | |
94 void Maximize() override; | |
95 void Minimize() override; | |
96 void Restore() override; | |
97 void SetCursor(PlatformCursor cursor) override; | |
98 void MoveCursorTo(const gfx::Point& location) override; | |
99 void ConfineCursorToBounds(const gfx::Rect& bounds) override; | |
100 PlatformImeController* GetPlatformImeController() override; | |
101 | |
102 // PlatformEventDispatcher: | |
103 bool CanDispatchEvent(const PlatformEvent& event) override; | |
104 uint32_t DispatchEvent(const PlatformEvent& event) override; | |
105 | |
106 private: | |
107 PlatformWindowDelegate* delegate_; | |
108 LibeglplatformShimLoader* eglplatform_shim_; | |
109 EventFactoryEvdev* event_factory_; | |
110 gfx::Rect bounds_; | |
111 ShimNativeWindowId window_id_; | |
112 | |
113 DISALLOW_COPY_AND_ASSIGN(EgltestWindow); | |
114 }; | |
115 | |
116 EgltestWindow::EgltestWindow(PlatformWindowDelegate* delegate, | |
117 LibeglplatformShimLoader* eglplatform_shim, | |
118 EventFactoryEvdev* event_factory, | |
119 const gfx::Rect& bounds) | |
120 : delegate_(delegate), | |
121 eglplatform_shim_(eglplatform_shim), | |
122 event_factory_(event_factory), | |
123 bounds_(bounds), | |
124 window_id_(SHIM_NO_WINDOW_ID) { | |
125 window_id_ = eglplatform_shim_->ShimCreateWindow(); | |
126 delegate_->OnAcceleratedWidgetAvailable(window_id_, 1.f); | |
127 ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this); | |
128 } | |
129 | |
130 EgltestWindow::~EgltestWindow() { | |
131 ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this); | |
132 if (window_id_ != SHIM_NO_WINDOW_ID) | |
133 eglplatform_shim_->ShimDestroyWindow(window_id_); | |
134 } | |
135 | |
136 gfx::Rect EgltestWindow::GetBounds() { | |
137 return bounds_; | |
138 } | |
139 | |
140 void EgltestWindow::SetBounds(const gfx::Rect& bounds) { | |
141 bounds_ = bounds; | |
142 delegate_->OnBoundsChanged(bounds); | |
143 } | |
144 | |
145 void EgltestWindow::SetTitle(const base::string16& title) { | |
146 } | |
147 | |
148 void EgltestWindow::Show() { | |
149 } | |
150 | |
151 void EgltestWindow::Hide() { | |
152 } | |
153 | |
154 void EgltestWindow::Close() { | |
155 } | |
156 | |
157 void EgltestWindow::SetCapture() { | |
158 } | |
159 | |
160 void EgltestWindow::ReleaseCapture() { | |
161 } | |
162 | |
163 void EgltestWindow::ToggleFullscreen() { | |
164 } | |
165 | |
166 void EgltestWindow::Maximize() { | |
167 } | |
168 | |
169 void EgltestWindow::Minimize() { | |
170 } | |
171 | |
172 void EgltestWindow::Restore() { | |
173 } | |
174 | |
175 void EgltestWindow::SetCursor(PlatformCursor cursor) { | |
176 } | |
177 | |
178 void EgltestWindow::MoveCursorTo(const gfx::Point& location) { | |
179 event_factory_->WarpCursorTo(window_id_, gfx::PointF(location)); | |
180 } | |
181 | |
182 void EgltestWindow::ConfineCursorToBounds(const gfx::Rect& bounds) { | |
183 } | |
184 | |
185 PlatformImeController* EgltestWindow::GetPlatformImeController() { | |
186 return nullptr; | |
187 } | |
188 | |
189 bool EgltestWindow::CanDispatchEvent(const ui::PlatformEvent& ne) { | |
190 return true; | |
191 } | |
192 | |
193 uint32_t EgltestWindow::DispatchEvent(const ui::PlatformEvent& native_event) { | |
194 DCHECK(native_event); | |
195 Event* event = static_cast<Event*>(native_event); | |
196 if (event->IsTouchEvent()) { | |
197 ScaleTouchEvent(static_cast<TouchEvent*>(event), | |
198 gfx::SizeF(bounds_.size())); | |
199 } | |
200 | |
201 DispatchEventFromNativeUiEvent( | |
202 native_event, base::Bind(&PlatformWindowDelegate::DispatchEvent, | |
203 base::Unretained(delegate_))); | |
204 | |
205 return ui::POST_DISPATCH_STOP_PROPAGATION; | |
206 } | |
207 | |
208 // EGL surface wrapper for libeglplatform_shim. | |
209 // | |
210 // This just manages the native window lifetime using | |
211 // ShimGetNativeWindow & ShimReleaseNativeWindow. | |
212 class SurfaceOzoneEgltest : public SurfaceOzoneEGL { | |
213 public: | |
214 SurfaceOzoneEgltest(ShimNativeWindowId window_id, | |
215 LibeglplatformShimLoader* eglplatform_shim) | |
216 : eglplatform_shim_(eglplatform_shim) { | |
217 native_window_ = eglplatform_shim_->ShimGetNativeWindow(window_id); | |
218 } | |
219 ~SurfaceOzoneEgltest() override { | |
220 bool ret = eglplatform_shim_->ShimReleaseNativeWindow(native_window_); | |
221 DCHECK(ret); | |
222 } | |
223 | |
224 intptr_t GetNativeWindow() override { return native_window_; } | |
225 | |
226 bool OnSwapBuffers() override { return true; } | |
227 | |
228 void OnSwapBuffersAsync(const SwapCompletionCallback& callback) override { | |
229 callback.Run(gfx::SwapResult::SWAP_ACK); | |
230 } | |
231 | |
232 bool ResizeNativeWindow(const gfx::Size& viewport_size) override { | |
233 return true; | |
234 } | |
235 | |
236 std::unique_ptr<gfx::VSyncProvider> CreateVSyncProvider() override { | |
237 return nullptr; | |
238 } | |
239 | |
240 void* /* EGLConfig */ GetEGLSurfaceConfig( | |
241 const EglConfigCallbacks& egl) override { | |
242 EGLint broken_props[] = { | |
243 EGL_RENDERABLE_TYPE, | |
244 EGL_OPENGL_ES2_BIT, | |
245 EGL_SURFACE_TYPE, | |
246 EGL_WINDOW_BIT | EGL_PBUFFER_BIT, | |
247 EGL_NONE, | |
248 }; | |
249 return ChooseEGLConfig(egl, broken_props); | |
250 } | |
251 | |
252 private: | |
253 LibeglplatformShimLoader* eglplatform_shim_; | |
254 intptr_t native_window_; | |
255 }; | |
256 | |
257 // EGL surface factory for libeglplatform_shim. | |
258 // | |
259 // This finds the right EGL/GLES2 libraries for loading, and creates | |
260 // a single native window via ShimCreateWindow for drawing | |
261 // into. | |
262 class SurfaceFactoryEgltest : public ui::SurfaceFactoryOzone { | |
263 public: | |
264 SurfaceFactoryEgltest(LibeglplatformShimLoader* eglplatform_shim) | |
265 : eglplatform_shim_(eglplatform_shim) {} | |
266 ~SurfaceFactoryEgltest() override { | |
267 DCHECK(thread_checker_.CalledOnValidThread()); | |
268 } | |
269 | |
270 // SurfaceFactoryOzone: | |
271 intptr_t GetNativeDisplay() override; | |
272 std::unique_ptr<SurfaceOzoneEGL> CreateEGLSurfaceForWidget( | |
273 gfx::AcceleratedWidget widget) override; | |
274 bool LoadEGLGLES2Bindings( | |
275 AddGLLibraryCallback add_gl_library, | |
276 SetGLGetProcAddressProcCallback set_gl_get_proc_address) override; | |
277 | |
278 private: | |
279 LibeglplatformShimLoader* eglplatform_shim_; | |
280 base::ThreadChecker thread_checker_; | |
281 }; | |
282 | |
283 intptr_t SurfaceFactoryEgltest::GetNativeDisplay() { | |
284 DCHECK(thread_checker_.CalledOnValidThread()); | |
285 return eglplatform_shim_->ShimGetNativeDisplay(); | |
286 } | |
287 | |
288 std::unique_ptr<SurfaceOzoneEGL> | |
289 SurfaceFactoryEgltest::CreateEGLSurfaceForWidget( | |
290 gfx::AcceleratedWidget widget) { | |
291 DCHECK(thread_checker_.CalledOnValidThread()); | |
292 return base::WrapUnique<SurfaceOzoneEGL>( | |
293 new SurfaceOzoneEgltest(widget, eglplatform_shim_)); | |
294 } | |
295 | |
296 bool SurfaceFactoryEgltest::LoadEGLGLES2Bindings( | |
297 AddGLLibraryCallback add_gl_library, | |
298 SetGLGetProcAddressProcCallback set_gl_get_proc_address) { | |
299 DCHECK(thread_checker_.CalledOnValidThread()); | |
300 const char* egl_soname = eglplatform_shim_->ShimQueryString(SHIM_EGL_LIBRARY); | |
301 const char* gles_soname = | |
302 eglplatform_shim_->ShimQueryString(SHIM_GLES_LIBRARY); | |
303 if (!egl_soname) | |
304 egl_soname = kDefaultEglSoname; | |
305 if (!gles_soname) | |
306 gles_soname = kDefaultGlesSoname; | |
307 | |
308 return ::ui::LoadEGLGLES2Bindings(add_gl_library, set_gl_get_proc_address, | |
309 egl_soname, gles_soname); | |
310 } | |
311 | |
312 // Test platform for EGL. | |
313 // | |
314 // This is a tiny EGL-based platform. Creation of the native window is | |
315 // handled by a separate library called eglplatform_shim.so.1 because | |
316 // this itself is platform specific and we want to test out multiple | |
317 // hardware platforms. | |
318 class OzonePlatformEgltest : public OzonePlatform { | |
319 public: | |
320 OzonePlatformEgltest() : shim_initialized_(false) {} | |
321 ~OzonePlatformEgltest() override { | |
322 if (shim_initialized_) | |
323 eglplatform_shim_.ShimTerminate(); | |
324 } | |
325 | |
326 void LoadShim() { | |
327 std::string library = GetShimLibraryName(); | |
328 | |
329 if (eglplatform_shim_.Load(library)) | |
330 return; | |
331 | |
332 base::FilePath module_path; | |
333 if (!PathService::Get(base::DIR_MODULE, &module_path)) | |
334 LOG(ERROR) << "failed to get DIR_MODULE from PathService"; | |
335 base::FilePath library_path = module_path.Append(library); | |
336 | |
337 if (eglplatform_shim_.Load(library_path.value())) | |
338 return; | |
339 | |
340 LOG(FATAL) << "failed to load " << library; | |
341 } | |
342 | |
343 void Initialize() { | |
344 LoadShim(); | |
345 shim_initialized_ = eglplatform_shim_.ShimInitialize(); | |
346 } | |
347 | |
348 // OzonePlatform: | |
349 ui::SurfaceFactoryOzone* GetSurfaceFactoryOzone() override { | |
350 return surface_factory_ozone_.get(); | |
351 } | |
352 OverlayManagerOzone* GetOverlayManager() override { | |
353 return overlay_manager_.get(); | |
354 } | |
355 CursorFactoryOzone* GetCursorFactoryOzone() override { | |
356 return cursor_factory_ozone_.get(); | |
357 } | |
358 InputController* GetInputController() override { | |
359 return event_factory_ozone_->input_controller(); | |
360 } | |
361 GpuPlatformSupport* GetGpuPlatformSupport() override { | |
362 return gpu_platform_support_.get(); | |
363 } | |
364 GpuPlatformSupportHost* GetGpuPlatformSupportHost() override { | |
365 return gpu_platform_support_host_.get(); | |
366 } | |
367 std::unique_ptr<SystemInputInjector> CreateSystemInputInjector() override { | |
368 return nullptr; // no input injection support. | |
369 } | |
370 std::unique_ptr<PlatformWindow> CreatePlatformWindow( | |
371 PlatformWindowDelegate* delegate, | |
372 const gfx::Rect& bounds) override { | |
373 return base::WrapUnique<PlatformWindow>(new EgltestWindow( | |
374 delegate, &eglplatform_shim_, event_factory_ozone_.get(), bounds)); | |
375 } | |
376 std::unique_ptr<NativeDisplayDelegate> CreateNativeDisplayDelegate() | |
377 override { | |
378 return base::WrapUnique(new NativeDisplayDelegateOzone()); | |
379 } | |
380 | |
381 void InitializeUI() override { | |
382 device_manager_ = CreateDeviceManager(); | |
383 overlay_manager_.reset(new StubOverlayManager()); | |
384 KeyboardLayoutEngineManager::SetKeyboardLayoutEngine( | |
385 base::WrapUnique(new StubKeyboardLayoutEngine())); | |
386 event_factory_ozone_.reset(new EventFactoryEvdev( | |
387 NULL, device_manager_.get(), | |
388 KeyboardLayoutEngineManager::GetKeyboardLayoutEngine())); | |
389 cursor_factory_ozone_.reset(new CursorFactoryOzone()); | |
390 gpu_platform_support_host_.reset(CreateStubGpuPlatformSupportHost()); | |
391 } | |
392 | |
393 void InitializeGPU() override { | |
394 surface_factory_ozone_.reset(new SurfaceFactoryEgltest(&eglplatform_shim_)); | |
395 gpu_platform_support_.reset(CreateStubGpuPlatformSupport()); | |
396 } | |
397 | |
398 private: | |
399 LibeglplatformShimLoader eglplatform_shim_; | |
400 std::unique_ptr<DeviceManager> device_manager_; | |
401 std::unique_ptr<SurfaceFactoryEgltest> surface_factory_ozone_; | |
402 std::unique_ptr<EventFactoryEvdev> event_factory_ozone_; | |
403 std::unique_ptr<CursorFactoryOzone> cursor_factory_ozone_; | |
404 std::unique_ptr<GpuPlatformSupport> gpu_platform_support_; | |
405 std::unique_ptr<GpuPlatformSupportHost> gpu_platform_support_host_; | |
406 std::unique_ptr<OverlayManagerOzone> overlay_manager_; | |
407 | |
408 bool shim_initialized_; | |
409 | |
410 DISALLOW_COPY_AND_ASSIGN(OzonePlatformEgltest); | |
411 }; | |
412 | |
413 } // namespace | |
414 | |
415 OzonePlatform* CreateOzonePlatformEgltest() { | |
416 OzonePlatformEgltest* platform = new OzonePlatformEgltest; | |
417 platform->Initialize(); | |
418 return platform; | |
419 } | |
420 | |
421 } // namespace ui | |
OLD | NEW |