Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / ozone / wayland / display.cc
index 5b72eb0..c5727bb 100644 (file)
@@ -5,15 +5,23 @@
 
 #include "ozone/wayland/display.h"
 
+#include <EGL/egl.h>
+#include <string>
+
+#include "base/files/file_path.h"
+#include "base/native_library.h"
 #include "base/stl_util.h"
 #include "ozone/ui/events/event_factory_ozone_wayland.h"
 #include "ozone/ui/events/output_change_observer.h"
+#include "ozone/ui/gfx/ozone_display.h"
 #include "ozone/wayland/display_poll_thread.h"
 #include "ozone/wayland/input/cursor.h"
 #include "ozone/wayland/input_device.h"
 #include "ozone/wayland/screen.h"
+#include "ozone/wayland/egl/surface_ozone_wayland.h"
 #include "ozone/wayland/shell/shell.h"
 #include "ozone/wayland/window.h"
+#include "ui/gfx/ozone/surface_ozone_egl.h"
 
 namespace ozonewayland {
 WaylandDisplay* WaylandDisplay::instance_ = NULL;
@@ -31,37 +39,14 @@ WaylandDisplay::WaylandDisplay(RegistrationType type) : display_(NULL),
     widget_map_(),
     serial_(0),
     processing_events_(false) {
-  display_ = wl_display_connect(NULL);
-  if (!display_)
-    return;
-
-  instance_ = this;
-  static const struct wl_registry_listener registry_all = {
-    WaylandDisplay::DisplayHandleGlobal
-  };
-
-  static const struct wl_registry_listener registry_output = {
-    WaylandDisplay::DisplayHandleOutputOnly
-  };
-
-  registry_ = wl_display_get_registry(display_);
-  if (type == RegisterAsNeeded) {
-    wl_registry_add_listener(registry_, &registry_all, this);
-    shell_ = new WaylandShell();
-  } else {
-    wl_registry_add_listener(registry_, &registry_output, this);
-  }
-
-  if (wl_display_roundtrip(display_) < 0)
-    terminate();
-  else if (type == RegisterAsNeeded) {
-    ui::WindowStateChangeHandler::SetInstance(this);
-    display_poll_thread_ = new WaylandDisplayPollThread(display_);
-  }
+  if (type == RegisterAsNeeded)
+    gfx::OzoneDisplay::SetInstance(this);
+  else
+    InitializeDisplay(WaylandDisplay::RegisterOutputOnly);
 }
 
 WaylandDisplay::~WaylandDisplay() {
-  terminate();
+  Terminate();
 }
 
 const std::list<WaylandScreen*>& WaylandDisplay::GetScreenList() const {
@@ -76,22 +61,161 @@ struct wl_text_input_manager* WaylandDisplay::GetTextInputManager() const {
   return text_input_manager_;
 }
 
+void WaylandDisplay::SyncDisplay() {
+  wl_display_roundtrip(display_);
+}
+
 void WaylandDisplay::FlushDisplay() {
   wl_display_flush(display_);
 }
 
-void WaylandDisplay::SyncDisplay() {
-  wl_display_roundtrip(display_);
+void WaylandDisplay::DestroyWindow(unsigned w) {
+  std::map<unsigned, WaylandWindow*>::const_iterator it = widget_map_.find(w);
+  WaylandWindow* widget = it == widget_map_.end() ? NULL : it->second;
+  DCHECK(widget);
+  delete widget;
+  widget_map_.erase(w);
+  if (widget_map_.empty())
+    StopProcessingEvents();
 }
 
-wl_egl_window* WaylandDisplay::RealizeAcceleratedWidget(unsigned w) {
+gfx::AcceleratedWidget WaylandDisplay::GetNativeWindow(unsigned window_handle) {
   // Ensure we are processing wayland event requests.
   StartProcessingEvents();
-  WaylandWindow* widget = GetWidget(w);
+  WaylandWindow* widget = GetWidget(window_handle);
   DCHECK(widget);
   widget->RealizeAcceleratedWidget();
 
-  return widget->egl_window();
+  return (gfx::AcceleratedWidget)widget->egl_window();
+}
+
+gfx::SurfaceFactoryOzone::HardwareState
+WaylandDisplay::InitializeHardware() {
+  InitializeDisplay(WaylandDisplay::RegisterAsNeeded);
+  if (!display_) {
+    LOG(ERROR) << "WaylandDisplay failed to initialize hardware";
+    return gfx::SurfaceFactoryOzone::FAILED;
+  }
+
+  return gfx::SurfaceFactoryOzone::INITIALIZED;
+}
+
+void WaylandDisplay::ShutdownHardware() {
+  Terminate();
+}
+
+intptr_t WaylandDisplay::GetNativeDisplay() {
+  return (intptr_t)display_;
+}
+
+gfx::AcceleratedWidget WaylandDisplay::GetAcceleratedWidget() {
+  static int opaque_handle = 0;
+  opaque_handle++;
+  ui::WindowStateChangeHandler::GetInstance()->SetWidgetState(opaque_handle,
+                                                              ui::CREATE,
+                                                              0,
+                                                              0);
+
+  return (gfx::AcceleratedWidget)opaque_handle;
+}
+
+// TODO(vignatti): GPU process conceptually is the one that deals with hardware
+// details and therefore we assume that the window system connection should
+// happen in there only. There's a glitch with Chrome though, that creates its
+// frame contents requiring access to the window system, before the GPU process
+// even exists. In other words, Chrome runs
+// BrowserMainLoop::PreMainMessageLoopRun before GpuProcessHost::Get. If the
+// assumption of window system connection belongs to the GPU process is valid,
+// then I believe this Chrome behavior needs to be addressed upstream.
+//
+// For now, we create another window system connection to look ahead the needed
+// output properties that Chrome (among others) need and then close right after
+// that. I haven't measured how long it takes to open a Wayland connection,
+// listen all the interface the compositor sends and close it, but _for_ _sure_
+// it slows down the overall initialization time of Chromium targets.
+// Therefore, this is something that has to be solved in the future, moving all
+// Chrome tasks after GPU process is created.
+//
+void WaylandDisplay::LookAheadOutputGeometry() {
+  WaylandDisplay disp_(WaylandDisplay::RegisterOutputOnly);
+  CHECK(disp_.display()) << "Ozone: Wayland server connection not found.";
+
+  while (disp_.PrimaryScreen()->Geometry().IsEmpty())
+    disp_.SyncDisplay();
+
+  ui::EventFactoryOzoneWayland* event_factory =
+      ui::EventFactoryOzoneWayland::GetInstance();
+  DCHECK(event_factory->GetOutputChangeObserver());
+
+  unsigned width = disp_.PrimaryScreen()->Geometry().width();
+  unsigned height = disp_.PrimaryScreen()->Geometry().height();
+  event_factory->GetOutputChangeObserver()->OnOutputSizeChanged(width, height);
+}
+
+scoped_ptr<gfx::SurfaceOzoneEGL> WaylandDisplay::CreateEGLSurfaceForWidget(
+    gfx::AcceleratedWidget w) {
+  return make_scoped_ptr<gfx::SurfaceOzoneEGL>(new SurfaceOzoneWayland(w));
+}
+
+bool WaylandDisplay::LoadEGLGLES2Bindings(
+    gfx::SurfaceFactoryOzone::AddGLLibraryCallback add_gl_library,
+    gfx::SurfaceFactoryOzone::SetGLGetProcAddressProcCallback setprocaddress) {
+  // The variable EGL_PLATFORM specifies native platform to be used by the
+  // drivers (atleast on Mesa). When the variable is not set, Mesa uses the
+  // first platform listed in --with-egl-platforms during compilation. Thus, we
+  // ensure here that wayland is set as the native platform. However, we don't
+  // override the EGL_PLATFORM value in case it has already been set.
+  setenv("EGL_PLATFORM", "wayland", 0);
+  base::NativeLibraryLoadError error;
+  base::NativeLibrary gles_library = base::LoadNativeLibrary(
+    base::FilePath("libGLESv2.so.2"), &error);
+
+  if (!gles_library) {
+    LOG(WARNING) << "Failed to load GLES library: " << error.ToString();
+    return false;
+  }
+
+  base::NativeLibrary egl_library = base::LoadNativeLibrary(
+    base::FilePath("libEGL.so.1"), &error);
+
+  if (!egl_library) {
+    LOG(WARNING) << "Failed to load EGL library: " << error.ToString();
+    base::UnloadNativeLibrary(gles_library);
+    return false;
+  }
+
+  GLGetProcAddressProc get_proc_address =
+      reinterpret_cast<GLGetProcAddressProc>(
+          base::GetFunctionPointerFromNativeLibrary(
+              egl_library, "eglGetProcAddress"));
+
+  if (!get_proc_address) {
+    LOG(ERROR) << "eglGetProcAddress not found.";
+    base::UnloadNativeLibrary(egl_library);
+    base::UnloadNativeLibrary(gles_library);
+    return false;
+  }
+
+  setprocaddress.Run(get_proc_address);
+  add_gl_library.Run(egl_library);
+  add_gl_library.Run(gles_library);
+  return true;
+}
+
+const int32*
+WaylandDisplay::GetEGLSurfaceProperties(const int32* desired_list) {
+  static const EGLint kConfigAttribs[] = {
+    EGL_BUFFER_SIZE, 32,
+    EGL_ALPHA_SIZE, 8,
+    EGL_BLUE_SIZE, 8,
+    EGL_GREEN_SIZE, 8,
+    EGL_RED_SIZE, 8,
+    EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+    EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+    EGL_NONE
+  };
+
+  return kConfigAttribs;
 }
 
 void WaylandDisplay::SetWidgetState(unsigned w,
@@ -142,20 +266,6 @@ void WaylandDisplay::SetWidgetState(unsigned w,
     case ui::HIDE:
       NOTIMPLEMENTED() << " HIDE " << w;
       break;
-    case ui::RESIZE:
-    {
-      WaylandWindow* window = GetWidget(w);
-      DCHECK(window);
-      window->Resize(width, height);
-      break;
-    }
-    case ui::DESTROYED:
-    {
-      DestroyWindow(w);
-      if (widget_map_.empty())
-        StopProcessingEvents();
-      break;
-    }
     default:
       break;
   }
@@ -199,6 +309,37 @@ void WaylandDisplay::SetWidgetAttributes(unsigned widget,
   }
 }
 
+void WaylandDisplay::InitializeDisplay(RegistrationType type) {
+  DCHECK(!display_);
+  display_ = wl_display_connect(NULL);
+  if (!display_)
+    return;
+
+  instance_ = this;
+  static const struct wl_registry_listener registry_all = {
+    WaylandDisplay::DisplayHandleGlobal
+  };
+
+  static const struct wl_registry_listener registry_output = {
+    WaylandDisplay::DisplayHandleOutputOnly
+  };
+
+  registry_ = wl_display_get_registry(display_);
+  if (type == RegisterAsNeeded) {
+    wl_registry_add_listener(registry_, &registry_all, this);
+    shell_ = new WaylandShell();
+  } else {
+    wl_registry_add_listener(registry_, &registry_output, this);
+  }
+
+  if (wl_display_roundtrip(display_) < 0)
+    Terminate();
+  else if (type == RegisterAsNeeded) {
+    ui::WindowStateChangeHandler::SetInstance(this);
+    display_poll_thread_ = new WaylandDisplayPollThread(display_);
+  }
+}
+
 WaylandWindow* WaylandDisplay::CreateAcceleratedSurface(unsigned w) {
   WaylandWindow* window = new WaylandWindow(w);
   widget_map_[w] = window;
@@ -206,14 +347,6 @@ WaylandWindow* WaylandDisplay::CreateAcceleratedSurface(unsigned w) {
   return window;
 }
 
-void WaylandDisplay::DestroyWindow(unsigned w) {
-  std::map<unsigned, WaylandWindow*>::const_iterator it = widget_map_.find(w);
-  WaylandWindow* widget = it == widget_map_.end() ? NULL : it->second;
-  DCHECK(widget);
-  delete widget;
-  widget_map_.erase(w);
-}
-
 void WaylandDisplay::StartProcessingEvents() {
   DCHECK(display_poll_thread_);
   // Start polling for wayland events.
@@ -232,7 +365,7 @@ void WaylandDisplay::StopProcessingEvents() {
   }
 }
 
-void WaylandDisplay::terminate() {
+void WaylandDisplay::Terminate() {
   if (!widget_map_.empty()) {
     STLDeleteValues(&widget_map_);
     widget_map_.clear();
@@ -330,38 +463,4 @@ void WaylandDisplay::DisplayHandleOutputOnly(void *data,
   }
 }
 
-// static
-// TODO(vignatti): GPU process conceptually is the one that deals with hardware
-// details and therefore we assume that the window system connection should
-// happen in there only. There's a glitch with Chrome though, that creates its
-// frame contents requiring access to the window system, before the GPU process
-// even exists. In other words, Chrome runs
-// BrowserMainLoop::PreMainMessageLoopRun before GpuProcessHost::Get. If the
-// assumption of window system connection belongs to the GPU process is valid,
-// then I believe this Chrome behavior needs to be addressed upstream.
-//
-// For now, we create another window system connection to look ahead the needed
-// output properties that Chrome (among others) need and then close right after
-// that. I haven't measured how long it takes to open a Wayland connection,
-// listen all the interface the compositor sends and close it, but _for_ _sure_
-// it slows down the overall initialization time of Chromium targets.
-// Therefore, this is something that has to be solved in the future, moving all
-// Chrome tasks after GPU process is created.
-//
-void WaylandDisplay::LookAheadOutputGeometry() {
-  WaylandDisplay disp_(WaylandDisplay::RegisterOutputOnly);
-  CHECK(disp_.display()) << "Ozone: Wayland server connection not found.";
-
-  while (disp_.PrimaryScreen()->Geometry().IsEmpty())
-    disp_.SyncDisplay();
-
-  ui::EventFactoryOzoneWayland* event_factory =
-      ui::EventFactoryOzoneWayland::GetInstance();
-  DCHECK(event_factory->GetOutputChangeObserver());
-
-  unsigned width = disp_.PrimaryScreen()->Geometry().width();
-  unsigned height = disp_.PrimaryScreen()->Geometry().height();
-  event_factory->GetOutputChangeObserver()->OnOutputSizeChanged(width, height);
-}
-
 }  // namespace ozonewayland