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.
5 #include "ui/ozone/platform/egltest/ozone_platform_egltest.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"
29 #if defined(OS_CHROMEOS)
30 #include "ui/ozone/common/chromeos/native_display_delegate_ozone.h"
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";
42 // Get the library soname to load.
43 std::string GetShimLibraryName() {
45 scoped_ptr<base::Environment> env(base::Environment::Create());
46 if (env->GetVar(kEglplatformShim, &library))
48 return kEglplatformShimDefault;
51 class EgltestWindow : public PlatformWindow, public PlatformEventDispatcher {
53 EgltestWindow(PlatformWindowDelegate* delegate,
54 LibeglplatformShimLoader* eglplatform_shim,
55 EventFactoryEvdev* event_factory,
56 const gfx::Rect& bounds);
57 virtual ~EgltestWindow();
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;
74 // PlatformEventDispatcher:
75 virtual bool CanDispatchEvent(const PlatformEvent& event) OVERRIDE;
76 virtual uint32_t DispatchEvent(const PlatformEvent& event) OVERRIDE;
79 PlatformWindowDelegate* delegate_;
80 LibeglplatformShimLoader* eglplatform_shim_;
81 EventFactoryEvdev* event_factory_;
83 ShimNativeWindowId window_id_;
85 DISALLOW_COPY_AND_ASSIGN(EgltestWindow);
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),
96 window_id_(SHIM_NO_WINDOW_ID) {
97 window_id_ = eglplatform_shim_->ShimCreateWindow();
98 delegate_->OnAcceleratedWidgetAvailable(window_id_);
99 ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
102 EgltestWindow::~EgltestWindow() {
103 ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
104 if (window_id_ != SHIM_NO_WINDOW_ID)
105 eglplatform_shim_->ShimDestroyWindow(window_id_);
108 gfx::Rect EgltestWindow::GetBounds() {
112 void EgltestWindow::SetBounds(const gfx::Rect& bounds) {
114 delegate_->OnBoundsChanged(bounds);
117 void EgltestWindow::Show() {
120 void EgltestWindow::Hide() {
123 void EgltestWindow::Close() {
126 void EgltestWindow::SetCapture() {
129 void EgltestWindow::ReleaseCapture() {
132 void EgltestWindow::ToggleFullscreen() {
135 void EgltestWindow::Maximize() {
138 void EgltestWindow::Minimize() {
141 void EgltestWindow::Restore() {
144 void EgltestWindow::SetCursor(PlatformCursor cursor) {
147 void EgltestWindow::MoveCursorTo(const gfx::Point& location) {
148 event_factory_->WarpCursorTo(window_id_, location);
151 bool EgltestWindow::CanDispatchEvent(const ui::PlatformEvent& ne) {
155 uint32_t EgltestWindow::DispatchEvent(const ui::PlatformEvent& native_event) {
156 DispatchEventFromNativeUiEvent(
158 base::Bind(&PlatformWindowDelegate::DispatchEvent,
159 base::Unretained(delegate_)));
161 return ui::POST_DISPATCH_STOP_PROPAGATION;
164 // EGL surface wrapper for libeglplatform_shim.
166 // This just manages the native window lifetime using
167 // ShimGetNativeWindow & ShimReleaseNativeWindow.
168 class SurfaceOzoneEgltest : public SurfaceOzoneEGL {
170 SurfaceOzoneEgltest(ShimNativeWindowId window_id,
171 LibeglplatformShimLoader* eglplatform_shim)
172 : eglplatform_shim_(eglplatform_shim) {
173 native_window_ = eglplatform_shim_->ShimGetNativeWindow(window_id);
175 virtual ~SurfaceOzoneEgltest() {
176 bool ret = eglplatform_shim_->ShimReleaseNativeWindow(native_window_);
180 virtual intptr_t GetNativeWindow() OVERRIDE { return native_window_; }
182 virtual bool OnSwapBuffers() OVERRIDE { return true; }
184 virtual bool ResizeNativeWindow(const gfx::Size& viewport_size) OVERRIDE {
188 virtual scoped_ptr<gfx::VSyncProvider> CreateVSyncProvider() OVERRIDE {
189 return scoped_ptr<gfx::VSyncProvider>();
193 LibeglplatformShimLoader* eglplatform_shim_;
194 intptr_t native_window_;
197 // EGL surface factory for libeglplatform_shim.
199 // This finds the right EGL/GLES2 libraries for loading, and creates
200 // a single native window via ShimCreateWindow for drawing
202 class SurfaceFactoryEgltest : public ui::SurfaceFactoryOzone {
204 SurfaceFactoryEgltest(LibeglplatformShimLoader* eglplatform_shim)
205 : eglplatform_shim_(eglplatform_shim) {}
206 virtual ~SurfaceFactoryEgltest() {}
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;
219 LibeglplatformShimLoader* eglplatform_shim_;
222 intptr_t SurfaceFactoryEgltest::GetNativeDisplay() {
223 return eglplatform_shim_->ShimGetNativeDisplay();
226 scoped_ptr<SurfaceOzoneEGL> SurfaceFactoryEgltest::CreateEGLSurfaceForWidget(
227 gfx::AcceleratedWidget widget) {
228 return make_scoped_ptr<SurfaceOzoneEGL>(
229 new SurfaceOzoneEgltest(widget, eglplatform_shim_));
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);
239 egl_soname = kDefaultEglSoname;
241 gles_soname = kDefaultGlesSoname;
243 base::NativeLibraryLoadError error;
244 base::NativeLibrary egl_library =
245 base::LoadNativeLibrary(base::FilePath(egl_soname), &error);
247 LOG(WARNING) << "Failed to load EGL library: " << error.ToString();
251 base::NativeLibrary gles_library =
252 base::LoadNativeLibrary(base::FilePath(gles_soname), &error);
254 LOG(WARNING) << "Failed to load GLES library: " << error.ToString();
255 base::UnloadNativeLibrary(egl_library);
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);
270 set_gl_get_proc_address.Run(get_proc_address);
271 add_gl_library.Run(egl_library);
272 add_gl_library.Run(gles_library);
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,
286 // Test platform for EGL.
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 {
294 OzonePlatformEgltest() : shim_initialized_(false) {}
295 virtual ~OzonePlatformEgltest() {
296 if (shim_initialized_)
297 eglplatform_shim_.ShimTerminate();
301 std::string library = GetShimLibraryName();
303 if (eglplatform_shim_.Load(library))
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);
311 if (eglplatform_shim_.Load(library_path.value()))
314 LOG(FATAL) << "failed to load " << library;
319 shim_initialized_ = eglplatform_shim_.ShimInitialize();
323 virtual ui::SurfaceFactoryOzone* GetSurfaceFactoryOzone() OVERRIDE {
324 return surface_factory_ozone_.get();
326 virtual CursorFactoryOzone* GetCursorFactoryOzone() OVERRIDE {
327 return cursor_factory_ozone_.get();
329 virtual GpuPlatformSupport* GetGpuPlatformSupport() OVERRIDE {
330 return gpu_platform_support_.get();
332 virtual GpuPlatformSupportHost* GetGpuPlatformSupportHost() OVERRIDE {
333 return gpu_platform_support_host_.get();
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,
341 event_factory_ozone_.get(),
345 #if defined(OS_CHROMEOS)
346 virtual scoped_ptr<NativeDisplayDelegate> CreateNativeDisplayDelegate()
348 return scoped_ptr<NativeDisplayDelegate>(new NativeDisplayDelegateOzone());
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());
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());
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_;
379 bool shim_initialized_;
381 DISALLOW_COPY_AND_ASSIGN(OzonePlatformEgltest);
386 OzonePlatform* CreateOzonePlatformEgltest() {
387 OzonePlatformEgltest* platform = new OzonePlatformEgltest;
388 platform->Initialize();