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/dri/gbm_surface_factory.h" 6 7 #include <EGL/egl.h> 8 #include <gbm.h> 9 10 #include "base/files/file_path.h" 11 #include "ui/ozone/platform/dri/buffer_data.h" 12 #include "ui/ozone/platform/dri/dri_vsync_provider.h" 13 #include "ui/ozone/platform/dri/gbm_surface.h" 14 #include "ui/ozone/platform/dri/hardware_display_controller.h" 15 #include "ui/ozone/platform/dri/scanout_surface.h" 16 #include "ui/ozone/platform/dri/screen_manager.h" 17 #include "ui/ozone/public/surface_ozone_egl.h" 18 19 namespace ui { 20 21 namespace { 22 23 class GbmSurfaceAdapter : public ui::SurfaceOzoneEGL { 24 public: 25 GbmSurfaceAdapter(const base::WeakPtr<HardwareDisplayController>& controller); 26 virtual ~GbmSurfaceAdapter(); 27 28 // SurfaceOzoneEGL: 29 virtual intptr_t GetNativeWindow() OVERRIDE; 30 virtual bool ResizeNativeWindow(const gfx::Size& viewport_size) OVERRIDE; 31 virtual bool OnSwapBuffers() OVERRIDE; 32 virtual scoped_ptr<gfx::VSyncProvider> CreateVSyncProvider() OVERRIDE; 33 34 private: 35 base::WeakPtr<HardwareDisplayController> controller_; 36 37 DISALLOW_COPY_AND_ASSIGN(GbmSurfaceAdapter); 38 }; 39 40 GbmSurfaceAdapter::GbmSurfaceAdapter( 41 const base::WeakPtr<HardwareDisplayController>& controller) 42 : controller_(controller) {} 43 44 GbmSurfaceAdapter::~GbmSurfaceAdapter() {} 45 46 intptr_t GbmSurfaceAdapter::GetNativeWindow() { 47 if (!controller_) 48 return 0; 49 50 return reinterpret_cast<intptr_t>( 51 static_cast<GbmSurface*>(controller_->surface())->native_surface()); 52 } 53 54 bool GbmSurfaceAdapter::ResizeNativeWindow(const gfx::Size& viewport_size) { 55 NOTIMPLEMENTED(); 56 return false; 57 } 58 59 bool GbmSurfaceAdapter::OnSwapBuffers() { 60 if (!controller_) 61 return false; 62 63 static_cast<GbmSurface*>(controller_->surface())->LockCurrentDrawable(); 64 if (controller_->SchedulePageFlip()) { 65 controller_->WaitForPageFlipEvent(); 66 return true; 67 } 68 69 return false; 70 } 71 72 scoped_ptr<gfx::VSyncProvider> GbmSurfaceAdapter::CreateVSyncProvider() { 73 return scoped_ptr<gfx::VSyncProvider>(new DriVSyncProvider(controller_)); 74 } 75 76 } // namespace 77 78 GbmSurfaceFactory::GbmSurfaceFactory(DriWrapper* dri, 79 gbm_device* device, 80 ScreenManager* screen_manager) 81 : DriSurfaceFactory(dri, screen_manager), 82 device_(device) {} 83 84 GbmSurfaceFactory::~GbmSurfaceFactory() {} 85 86 intptr_t GbmSurfaceFactory::GetNativeDisplay() { 87 CHECK(state_ == INITIALIZED); 88 return reinterpret_cast<intptr_t>(device_); 89 } 90 91 const int32* GbmSurfaceFactory::GetEGLSurfaceProperties( 92 const int32* desired_list) { 93 static const int32 kConfigAttribs[] = { 94 EGL_BUFFER_SIZE, 32, 95 EGL_ALPHA_SIZE, 8, 96 EGL_BLUE_SIZE, 8, 97 EGL_GREEN_SIZE, 8, 98 EGL_RED_SIZE, 8, 99 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 100 EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 101 EGL_NONE 102 }; 103 104 return kConfigAttribs; 105 } 106 107 bool GbmSurfaceFactory::LoadEGLGLES2Bindings( 108 AddGLLibraryCallback add_gl_library, 109 SetGLGetProcAddressProcCallback set_gl_get_proc_address) { 110 base::NativeLibraryLoadError error; 111 base::NativeLibrary gles_library = base::LoadNativeLibrary( 112 base::FilePath("libGLESv2.so.2"), 113 &error); 114 if (!gles_library) { 115 LOG(WARNING) << "Failed to load GLES library: " << error.ToString(); 116 return false; 117 } 118 119 base::NativeLibrary egl_library = base::LoadNativeLibrary( 120 base::FilePath("libEGL.so.1"), 121 &error); 122 if (!egl_library) { 123 LOG(WARNING) << "Failed to load EGL library: " << error.ToString(); 124 base::UnloadNativeLibrary(gles_library); 125 return false; 126 } 127 128 GLGetProcAddressProc get_proc_address = 129 reinterpret_cast<GLGetProcAddressProc>( 130 base::GetFunctionPointerFromNativeLibrary( 131 egl_library, "eglGetProcAddress")); 132 if (!get_proc_address) { 133 LOG(ERROR) << "eglGetProcAddress not found."; 134 base::UnloadNativeLibrary(egl_library); 135 base::UnloadNativeLibrary(gles_library); 136 return false; 137 } 138 139 set_gl_get_proc_address.Run(get_proc_address); 140 add_gl_library.Run(egl_library); 141 add_gl_library.Run(gles_library); 142 143 return true; 144 } 145 146 scoped_ptr<ui::SurfaceOzoneEGL> GbmSurfaceFactory::CreateEGLSurfaceForWidget( 147 gfx::AcceleratedWidget w) { 148 CHECK(state_ == INITIALIZED); 149 ResetCursor(w); 150 151 return scoped_ptr<ui::SurfaceOzoneEGL>( 152 new GbmSurfaceAdapter(screen_manager_->GetDisplayController(w))); 153 } 154 155 gfx::NativeBufferOzone GbmSurfaceFactory::CreateNativeBuffer( 156 gfx::Size size, 157 BufferFormat format) { 158 uint32_t gbm_format = 0; 159 switch (format) { 160 case SurfaceFactoryOzone::UNKNOWN: 161 return 0; 162 // TODO(alexst): Setting this to XRGB for now to allow presentation 163 // as a primary plane but disallowing overlay transparency. Address this 164 // to allow both use cases. 165 case SurfaceFactoryOzone::RGBA_8888: 166 gbm_format = GBM_FORMAT_XRGB8888; 167 break; 168 case SurfaceFactoryOzone::RGB_888: 169 gbm_format = GBM_FORMAT_RGB888; 170 break; 171 } 172 gbm_bo* buffer_object = 173 gbm_bo_create(device_, 174 size.width(), 175 size.height(), 176 gbm_format, 177 GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); 178 if (!buffer_object) 179 return 0; 180 181 BufferData* data = BufferData::CreateData(drm_, buffer_object); 182 DCHECK(data) << "Failed to associate the buffer with the controller"; 183 184 return reinterpret_cast<gfx::NativeBufferOzone>(buffer_object); 185 } 186 187 } // namespace ui 188