Index: ui/gfx/ozone/dri/gbm_surface_factory.cc |
diff --git a/ui/gfx/ozone/dri/gbm_surface_factory.cc b/ui/gfx/ozone/dri/gbm_surface_factory.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c7d569d99694c0527ceca884741c26d9e232ebde |
--- /dev/null |
+++ b/ui/gfx/ozone/dri/gbm_surface_factory.cc |
@@ -0,0 +1,206 @@ |
+// Copyright 2013 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "ui/gfx/ozone/dri/gbm_surface_factory.h" |
+ |
+#include <drm.h> |
+#include <errno.h> |
+#include <fcntl.h> |
+#include <xf86drm.h> |
+ |
+#include "base/files/file_path.h" |
+#include "base/message_loop/message_loop.h" |
+#include "base/native_library.h" |
+#include "third_party/khronos/EGL/egl.h" |
+#include "third_party/khronos/EGL/eglext.h" |
+#include "third_party/mesa/src/src/gbm/main/gbm.h" |
+#include "third_party/skia/include/core/SkBitmapDevice.h" |
+#include "third_party/skia/include/core/SkCanvas.h" |
+#include "ui/gfx/ozone/dri/dri_wrapper.h" |
+#include "ui/gfx/ozone/dri/gbm_surface.h" |
+#include "ui/gfx/ozone/dri/hardware_display_controller.h" |
+#include "ui/gfx/ozone/dri/scanout_surface.h" |
+ |
+namespace gfx { |
+ |
+namespace { |
+ |
+typedef EGLBoolean (*eglSwapBuffersProc)(EGLDisplay dpy, EGLSurface surface); |
+ |
+static eglSwapBuffersProc g_native_egl_swap_buffers; |
+ |
+EGLBoolean CustomEglSwapBuffers(EGLDisplay dpy, EGLSurface surface) { |
+ EGLBoolean ret = g_native_egl_swap_buffers(dpy, surface); |
+ |
+ // TODO(dnicoara) Once we support multiple displays we need to keep a mapping |
+ // between |surface| and AcceleratedWidgets such that we can select the |
+ // widget based on the |surface|. |
+ if (ret) |
+ gfx::SurfaceFactoryOzone::GetInstance()->SchedulePageFlip(1); |
+ |
+ return ret; |
+} |
+ |
+} // namespace |
+ |
+GbmSurfaceFactory::GbmSurfaceFactory() |
+ : DriSurfaceFactory(), |
+ device_(NULL) { |
+} |
+ |
+GbmSurfaceFactory::~GbmSurfaceFactory() { |
+ if (state_ == INITIALIZED) |
+ ShutdownHardware(); |
+} |
+ |
+SurfaceFactoryOzone::HardwareState |
+GbmSurfaceFactory::InitializeHardware() { |
+ CHECK(state_ == UNINITIALIZED); |
+ |
+ if (DriSurfaceFactory::InitializeHardware() != INITIALIZED) |
+ return state_; |
+ |
+ device_ = gbm_create_device(drm_->get_fd()); |
+ |
+ if (!device_) { |
+ LOG(ERROR) << "Cannot create GBM device"; |
+ state_ = FAILED; |
+ return state_; |
+ } |
+ |
+ // TODO(dnicoara) Figure out where this initialization needs to be done. |
+ if (!controller_.get()) |
+ controller_.reset(new HardwareDisplayController()); |
+ |
+ state_ = INITIALIZED; |
+ return state_; |
+} |
+ |
+void GbmSurfaceFactory::ShutdownHardware() { |
+ CHECK(state_ == INITIALIZED); |
+ |
+ gbm_device_destroy(device_); |
+ DriSurfaceFactory::ShutdownHardware(); |
+} |
+ |
+intptr_t GbmSurfaceFactory::GetNativeDisplay() { |
+ CHECK(state_ == INITIALIZED); |
+ return reinterpret_cast<intptr_t>(device_); |
+} |
+ |
+const int32* GbmSurfaceFactory::GetEGLSurfaceProperties( |
+ const int32* desired_list) { |
+ static const int32 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; |
+} |
+ |
+bool GbmSurfaceFactory::LoadEGLGLES2Bindings( |
+ AddGLLibraryCallback add_gl_library, |
+ SetGLGetProcAddressProcCallback set_gl_get_proc_address) { |
+ std::string error; |
+ base::NativeLibrary gles_library = base::LoadNativeLibrary( |
+ base::FilePath("libGLESv2.so.2"), |
+ &error); |
+ if (!gles_library) { |
+ LOG(WARNING) << "Failed to load GLES library: " << error; |
+ 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; |
+ 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; |
+ } |
+ |
+ set_gl_get_proc_address.Run(get_proc_address); |
+ add_gl_library.Run(egl_library); |
+ add_gl_library.Run(gles_library); |
+ |
+ return true; |
+} |
+ |
+bool GbmSurfaceFactory::AttemptToResizeAcceleratedWidget( |
+ gfx::AcceleratedWidget w, |
+ const gfx::Rect& bounds) { |
+ return false; |
+} |
+ |
+SkCanvas* GbmSurfaceFactory::GetCanvasForWidget( |
+ gfx::AcceleratedWidget w) { |
+ CHECK(state_ == INITIALIZED); |
+ // TODO(dnicoara) Figure out how this is used and unhack. |
+ static SkBitmapDevice* device = new SkBitmapDevice( |
+ SkBitmap::kARGB_8888_Config, |
+ controller_->get_mode().hdisplay, |
+ controller_->get_mode().vdisplay); |
+ static SkCanvas canvas(device); |
+ return &canvas; |
+} |
+ |
+bool GbmSurfaceFactory::SchedulePageFlip(gfx::AcceleratedWidget w) { |
+ CHECK(state_ == INITIALIZED); |
+ |
+ // TODO(dnicoara) Once we can handle multiple displays this needs to be |
+ // changed. |
+ CHECK(w == 1); |
+ |
+ static_cast<GbmSurface*>(controller_->get_surface()) |
+ ->LockCurrentDrawable(); |
+ return DriSurfaceFactory::SchedulePageFlip(w); |
+} |
+ |
+void* GbmSurfaceFactory::GetFunctionPointerFromNativeLibrary( |
+ base::NativeLibrary library, |
+ const char* name) { |
+ void* function = SurfaceFactoryOzone::GetFunctionPointerFromNativeLibrary( |
+ library, |
+ name); |
+ |
+ if (strcmp(name, "eglSwapBuffers") == 0) { |
+ g_native_egl_swap_buffers = reinterpret_cast<eglSwapBuffersProc>(function); |
+ function = reinterpret_cast<void*>(CustomEglSwapBuffers); |
+ } |
+ |
+ return function; |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// DriSurfaceFactory private |
+ |
+ScanoutSurface* GbmSurfaceFactory::CreateSurface( |
+ HardwareDisplayController* controller) { |
+ return new GbmSurface(controller_.get(), device_); |
+} |
+ |
+gfx::AcceleratedWidget GbmSurfaceFactory::GetNativeWidget( |
+ ScanoutSurface* surface) { |
+ return reinterpret_cast<gfx::AcceleratedWidget>( |
+ static_cast<GbmSurface*>(surface)->get_native_surface()); |
+} |
+ |
+} // namespace gfx |