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