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/ozone_platform_gbm.h" 6 7#include <dlfcn.h> 8#include <gbm.h> 9#include <stdlib.h> 10 11#include "base/at_exit.h" 12#include "base/command_line.h" 13#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h" 14#include "ui/events/ozone/device/device_manager.h" 15#include "ui/events/ozone/evdev/event_factory_evdev.h" 16#include "ui/ozone/platform/dri/dri_cursor.h" 17#include "ui/ozone/platform/dri/dri_window.h" 18#include "ui/ozone/platform/dri/dri_window_delegate_manager.h" 19#include "ui/ozone/platform/dri/dri_window_delegate_proxy.h" 20#include "ui/ozone/platform/dri/dri_window_manager.h" 21#include "ui/ozone/platform/dri/dri_wrapper.h" 22#include "ui/ozone/platform/dri/gbm_buffer.h" 23#include "ui/ozone/platform/dri/gbm_surface.h" 24#include "ui/ozone/platform/dri/gbm_surface_factory.h" 25#include "ui/ozone/platform/dri/gpu_platform_support_gbm.h" 26#include "ui/ozone/platform/dri/gpu_platform_support_host_gbm.h" 27#include "ui/ozone/platform/dri/scanout_buffer.h" 28#include "ui/ozone/platform/dri/screen_manager.h" 29#include "ui/ozone/platform/dri/virtual_terminal_manager.h" 30#include "ui/ozone/public/cursor_factory_ozone.h" 31#include "ui/ozone/public/gpu_platform_support.h" 32#include "ui/ozone/public/gpu_platform_support_host.h" 33#include "ui/ozone/public/ozone_platform.h" 34#include "ui/ozone/public/ozone_switches.h" 35 36#if defined(OS_CHROMEOS) 37#include "ui/ozone/platform/dri/chromeos/display_message_handler.h" 38#include "ui/ozone/platform/dri/chromeos/native_display_delegate_dri.h" 39#include "ui/ozone/platform/dri/chromeos/native_display_delegate_proxy.h" 40#endif 41 42namespace ui { 43 44namespace { 45 46const char kDefaultGraphicsCardPath[] = "/dev/dri/card0"; 47 48class GbmBufferGenerator : public ScanoutBufferGenerator { 49 public: 50 GbmBufferGenerator(DriWrapper* dri) 51 : dri_(dri), 52 glapi_lib_(dlopen("libglapi.so.0", RTLD_LAZY | RTLD_GLOBAL)), 53 device_(gbm_create_device(dri_->get_fd())) { 54 if (!device_) 55 LOG(FATAL) << "Unable to initialize gbm for " << kDefaultGraphicsCardPath; 56 } 57 virtual ~GbmBufferGenerator() { 58 gbm_device_destroy(device_); 59 if (glapi_lib_) 60 dlclose(glapi_lib_); 61 } 62 63 gbm_device* device() const { return device_; } 64 65 virtual scoped_refptr<ScanoutBuffer> Create(const gfx::Size& size) OVERRIDE { 66 return GbmBuffer::CreateBuffer( 67 dri_, device_, SurfaceFactoryOzone::RGBA_8888, size, true); 68 } 69 70 protected: 71 DriWrapper* dri_; // Not owned. 72 73 // HACK: gbm drivers have broken linkage 74 void *glapi_lib_; 75 76 gbm_device* device_; 77 78 DISALLOW_COPY_AND_ASSIGN(GbmBufferGenerator); 79}; 80 81class OzonePlatformGbm : public OzonePlatform { 82 public: 83 OzonePlatformGbm(bool use_surfaceless) : use_surfaceless_(use_surfaceless) { 84 base::AtExitManager::RegisterTask( 85 base::Bind(&base::DeletePointer<OzonePlatformGbm>, this)); 86 } 87 virtual ~OzonePlatformGbm() {} 88 89 // OzonePlatform: 90 virtual ui::SurfaceFactoryOzone* GetSurfaceFactoryOzone() OVERRIDE { 91 return surface_factory_ozone_.get(); 92 } 93 virtual CursorFactoryOzone* GetCursorFactoryOzone() OVERRIDE { 94 return cursor_factory_ozone_.get(); 95 } 96 virtual GpuPlatformSupport* GetGpuPlatformSupport() OVERRIDE { 97 return gpu_platform_support_.get(); 98 } 99 virtual GpuPlatformSupportHost* GetGpuPlatformSupportHost() OVERRIDE { 100 return gpu_platform_support_host_.get(); 101 } 102 virtual scoped_ptr<PlatformWindow> CreatePlatformWindow( 103 PlatformWindowDelegate* delegate, 104 const gfx::Rect& bounds) OVERRIDE { 105 scoped_ptr<DriWindow> platform_window( 106 new DriWindow(delegate, 107 bounds, 108 scoped_ptr<DriWindowDelegate>(new DriWindowDelegateProxy( 109 window_manager_->NextAcceleratedWidget(), 110 gpu_platform_support_host_.get())), 111 event_factory_ozone_.get(), 112 ui_window_delegate_manager_.get(), 113 window_manager_.get())); 114 platform_window->Initialize(); 115 return platform_window.PassAs<PlatformWindow>(); 116 } 117#if defined(OS_CHROMEOS) 118 virtual scoped_ptr<NativeDisplayDelegate> CreateNativeDisplayDelegate() 119 OVERRIDE { 120 return scoped_ptr<NativeDisplayDelegate>(new NativeDisplayDelegateProxy( 121 gpu_platform_support_host_.get(), device_manager_.get())); 122 } 123#endif 124 virtual void InitializeUI() OVERRIDE { 125 vt_manager_.reset(new VirtualTerminalManager()); 126 ui_window_delegate_manager_.reset(new DriWindowDelegateManager()); 127 // Needed since the browser process creates the accelerated widgets and that 128 // happens through SFO. 129 surface_factory_ozone_.reset(new GbmSurfaceFactory(use_surfaceless_)); 130 device_manager_ = CreateDeviceManager(); 131 gpu_platform_support_host_.reset(new GpuPlatformSupportHostGbm()); 132 cursor_factory_ozone_.reset(new BitmapCursorFactoryOzone); 133 window_manager_.reset( 134 new DriWindowManager(gpu_platform_support_host_.get())); 135 event_factory_ozone_.reset(new EventFactoryEvdev(window_manager_->cursor(), 136 device_manager_.get())); 137 } 138 139 virtual void InitializeGPU() OVERRIDE { 140 dri_.reset(new DriWrapper(kDefaultGraphicsCardPath)); 141 dri_->Initialize(); 142 buffer_generator_.reset(new GbmBufferGenerator(dri_.get())); 143 screen_manager_.reset(new ScreenManager(dri_.get(), 144 buffer_generator_.get())); 145 gpu_window_delegate_manager_.reset(new DriWindowDelegateManager()); 146 if (!surface_factory_ozone_) 147 surface_factory_ozone_.reset(new GbmSurfaceFactory(use_surfaceless_)); 148 149 surface_factory_ozone_->InitializeGpu(dri_.get(), 150 buffer_generator_->device(), 151 screen_manager_.get(), 152 gpu_window_delegate_manager_.get()); 153 gpu_platform_support_.reset( 154 new GpuPlatformSupportGbm(surface_factory_ozone_.get(), 155 gpu_window_delegate_manager_.get(), 156 screen_manager_.get())); 157#if defined(OS_CHROMEOS) 158 gpu_platform_support_->AddHandler(scoped_ptr<GpuPlatformSupport>( 159 new DisplayMessageHandler( 160 scoped_ptr<NativeDisplayDelegateDri>(new NativeDisplayDelegateDri( 161 dri_.get(), 162 screen_manager_.get(), 163 NULL))))); 164#endif 165 if (surface_factory_ozone_->InitializeHardware() != 166 DriSurfaceFactory::INITIALIZED) 167 LOG(FATAL) << "failed to initialize display hardware"; 168 } 169 170 private: 171 bool use_surfaceless_; 172 scoped_ptr<VirtualTerminalManager> vt_manager_; 173 scoped_ptr<DriWrapper> dri_; 174 scoped_ptr<GbmBufferGenerator> buffer_generator_; 175 scoped_ptr<ScreenManager> screen_manager_; 176 scoped_ptr<DeviceManager> device_manager_; 177 178 scoped_ptr<GbmSurfaceFactory> surface_factory_ozone_; 179 scoped_ptr<BitmapCursorFactoryOzone> cursor_factory_ozone_; 180 scoped_ptr<EventFactoryEvdev> event_factory_ozone_; 181 182 scoped_ptr<GpuPlatformSupportGbm> gpu_platform_support_; 183 scoped_ptr<GpuPlatformSupportHostGbm> gpu_platform_support_host_; 184 185 scoped_ptr<DriWindowDelegateManager> gpu_window_delegate_manager_; 186 // TODO(dnicoara) Once we have a mock channel for the software path the window 187 // can own the delegates on the browser side. Remove this then. 188 scoped_ptr<DriWindowDelegateManager> ui_window_delegate_manager_; 189 190 // Browser side object only. 191 scoped_ptr<DriWindowManager> window_manager_; 192 193 DISALLOW_COPY_AND_ASSIGN(OzonePlatformGbm); 194}; 195 196} // namespace 197 198OzonePlatform* CreateOzonePlatformGbm() { 199 CommandLine* cmd = CommandLine::ForCurrentProcess(); 200 return new OzonePlatformGbm(cmd->HasSwitch(switches::kOzoneUseSurfaceless)); 201} 202 203} // namespace ui 204