OLD | NEW |
(Empty) | |
| 1 // Copyright 2013 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/gfx/ozone/dri/gbm_surface_factory.h" |
| 6 |
| 7 #include <drm.h> |
| 8 #include <errno.h> |
| 9 #include <fcntl.h> |
| 10 #include <xf86drm.h> |
| 11 |
| 12 #include "base/files/file_path.h" |
| 13 #include "base/message_loop/message_loop.h" |
| 14 #include "base/native_library.h" |
| 15 #include "third_party/khronos/EGL/egl.h" |
| 16 #include "third_party/khronos/EGL/eglext.h" |
| 17 #include "third_party/mesa/src/src/gbm/main/gbm.h" |
| 18 #include "third_party/skia/include/core/SkBitmapDevice.h" |
| 19 #include "third_party/skia/include/core/SkCanvas.h" |
| 20 #include "ui/gfx/ozone/dri/dri_wrapper.h" |
| 21 #include "ui/gfx/ozone/dri/gbm_surface.h" |
| 22 #include "ui/gfx/ozone/dri/hardware_display_controller.h" |
| 23 #include "ui/gfx/ozone/dri/scanout_surface.h" |
| 24 |
| 25 namespace gfx { |
| 26 |
| 27 namespace { |
| 28 |
| 29 typedef EGLBoolean (*eglSwapBuffersProc)(EGLDisplay dpy, EGLSurface surface); |
| 30 |
| 31 static eglSwapBuffersProc g_native_egl_swap_buffers; |
| 32 |
| 33 EGLBoolean CustomEglSwapBuffers(EGLDisplay dpy, EGLSurface surface) { |
| 34 EGLBoolean ret = g_native_egl_swap_buffers(dpy, surface); |
| 35 |
| 36 // TODO(dnicoara) Once we support multiple displays we need to keep a mapping |
| 37 // between |surface| and AcceleratedWidgets such that we can select the |
| 38 // widget based on the |surface|. |
| 39 if (ret) |
| 40 gfx::SurfaceFactoryOzone::GetInstance()->SchedulePageFlip(1); |
| 41 |
| 42 return ret; |
| 43 } |
| 44 |
| 45 } // namespace |
| 46 |
| 47 GbmSurfaceFactory::GbmSurfaceFactory() |
| 48 : DriSurfaceFactory(), |
| 49 device_(NULL) { |
| 50 } |
| 51 |
| 52 GbmSurfaceFactory::~GbmSurfaceFactory() { |
| 53 if (state_ == INITIALIZED) |
| 54 ShutdownHardware(); |
| 55 } |
| 56 |
| 57 SurfaceFactoryOzone::HardwareState |
| 58 GbmSurfaceFactory::InitializeHardware() { |
| 59 CHECK(state_ == UNINITIALIZED); |
| 60 |
| 61 if (DriSurfaceFactory::InitializeHardware() != INITIALIZED) |
| 62 return state_; |
| 63 |
| 64 device_ = gbm_create_device(drm_->get_fd()); |
| 65 |
| 66 if (!device_) { |
| 67 LOG(ERROR) << "Cannot create GBM device"; |
| 68 state_ = FAILED; |
| 69 return state_; |
| 70 } |
| 71 |
| 72 // TODO(dnicoara) Figure out where this initialization needs to be done. |
| 73 if (!controller_.get()) |
| 74 controller_.reset(new HardwareDisplayController()); |
| 75 |
| 76 state_ = INITIALIZED; |
| 77 return state_; |
| 78 } |
| 79 |
| 80 void GbmSurfaceFactory::ShutdownHardware() { |
| 81 CHECK(state_ == INITIALIZED); |
| 82 |
| 83 gbm_device_destroy(device_); |
| 84 DriSurfaceFactory::ShutdownHardware(); |
| 85 } |
| 86 |
| 87 intptr_t GbmSurfaceFactory::GetNativeDisplay() { |
| 88 CHECK(state_ == INITIALIZED); |
| 89 return reinterpret_cast<intptr_t>(device_); |
| 90 } |
| 91 |
| 92 const int32* GbmSurfaceFactory::GetEGLSurfaceProperties( |
| 93 const int32* desired_list) { |
| 94 static const int32 kConfigAttribs[] = { |
| 95 EGL_BUFFER_SIZE, 32, |
| 96 EGL_ALPHA_SIZE, 8, |
| 97 EGL_BLUE_SIZE, 8, |
| 98 EGL_GREEN_SIZE, 8, |
| 99 EGL_RED_SIZE, 8, |
| 100 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, |
| 101 EGL_SURFACE_TYPE, EGL_WINDOW_BIT, |
| 102 EGL_NONE |
| 103 }; |
| 104 |
| 105 return kConfigAttribs; |
| 106 } |
| 107 |
| 108 bool GbmSurfaceFactory::LoadEGLGLES2Bindings( |
| 109 AddGLLibraryCallback add_gl_library, |
| 110 SetGLGetProcAddressProcCallback set_gl_get_proc_address) { |
| 111 std::string error; |
| 112 base::NativeLibrary gles_library = base::LoadNativeLibrary( |
| 113 base::FilePath("libGLESv2.so.2"), |
| 114 &error); |
| 115 if (!gles_library) { |
| 116 LOG(WARNING) << "Failed to load GLES library: " << error; |
| 117 return false; |
| 118 } |
| 119 |
| 120 base::NativeLibrary egl_library = base::LoadNativeLibrary( |
| 121 base::FilePath("libEGL.so.1"), |
| 122 &error); |
| 123 if (!egl_library) { |
| 124 LOG(WARNING) << "Failed to load EGL library: " << error; |
| 125 base::UnloadNativeLibrary(gles_library); |
| 126 return false; |
| 127 } |
| 128 |
| 129 GLGetProcAddressProc get_proc_address = |
| 130 reinterpret_cast<GLGetProcAddressProc>( |
| 131 base::GetFunctionPointerFromNativeLibrary( |
| 132 egl_library, "eglGetProcAddress")); |
| 133 if (!get_proc_address) { |
| 134 LOG(ERROR) << "eglGetProcAddress not found."; |
| 135 base::UnloadNativeLibrary(egl_library); |
| 136 base::UnloadNativeLibrary(gles_library); |
| 137 return false; |
| 138 } |
| 139 |
| 140 set_gl_get_proc_address.Run(get_proc_address); |
| 141 add_gl_library.Run(egl_library); |
| 142 add_gl_library.Run(gles_library); |
| 143 |
| 144 return true; |
| 145 } |
| 146 |
| 147 bool GbmSurfaceFactory::AttemptToResizeAcceleratedWidget( |
| 148 gfx::AcceleratedWidget w, |
| 149 const gfx::Rect& bounds) { |
| 150 return false; |
| 151 } |
| 152 |
| 153 SkCanvas* GbmSurfaceFactory::GetCanvasForWidget( |
| 154 gfx::AcceleratedWidget w) { |
| 155 CHECK(state_ == INITIALIZED); |
| 156 // TODO(dnicoara) Figure out how this is used and unhack. |
| 157 static SkBitmapDevice* device = new SkBitmapDevice( |
| 158 SkBitmap::kARGB_8888_Config, |
| 159 controller_->get_mode().hdisplay, |
| 160 controller_->get_mode().vdisplay); |
| 161 static SkCanvas canvas(device); |
| 162 return &canvas; |
| 163 } |
| 164 |
| 165 bool GbmSurfaceFactory::SchedulePageFlip(gfx::AcceleratedWidget w) { |
| 166 CHECK(state_ == INITIALIZED); |
| 167 |
| 168 // TODO(dnicoara) Once we can handle multiple displays this needs to be |
| 169 // changed. |
| 170 CHECK(w == 1); |
| 171 |
| 172 static_cast<GbmSurface*>(controller_->get_surface()) |
| 173 ->LockCurrentDrawable(); |
| 174 return DriSurfaceFactory::SchedulePageFlip(w); |
| 175 } |
| 176 |
| 177 void* GbmSurfaceFactory::GetFunctionPointerFromNativeLibrary( |
| 178 base::NativeLibrary library, |
| 179 const char* name) { |
| 180 void* function = SurfaceFactoryOzone::GetFunctionPointerFromNativeLibrary( |
| 181 library, |
| 182 name); |
| 183 |
| 184 if (strcmp(name, "eglSwapBuffers") == 0) { |
| 185 g_native_egl_swap_buffers = reinterpret_cast<eglSwapBuffersProc>(function); |
| 186 function = reinterpret_cast<void*>(CustomEglSwapBuffers); |
| 187 } |
| 188 |
| 189 return function; |
| 190 } |
| 191 |
| 192 //////////////////////////////////////////////////////////////////////////////// |
| 193 // DriSurfaceFactory private |
| 194 |
| 195 ScanoutSurface* GbmSurfaceFactory::CreateSurface( |
| 196 HardwareDisplayController* controller) { |
| 197 return new GbmSurface(controller_.get(), device_); |
| 198 } |
| 199 |
| 200 gfx::AcceleratedWidget GbmSurfaceFactory::GetNativeWidget( |
| 201 ScanoutSurface* surface) { |
| 202 return reinterpret_cast<gfx::AcceleratedWidget>( |
| 203 static_cast<GbmSurface*>(surface)->get_native_surface()); |
| 204 } |
| 205 |
| 206 } // namespace gfx |
OLD | NEW |