Home | History | Annotate | Download | only in dri
      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 
     42 namespace ui {
     43 
     44 namespace {
     45 
     46 const char kDefaultGraphicsCardPath[] = "/dev/dri/card0";
     47 
     48 class 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 
     81 class 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 
    198 OzonePlatform* CreateOzonePlatformGbm() {
    199   CommandLine* cmd = CommandLine::ForCurrentProcess();
    200   return new OzonePlatformGbm(cmd->HasSwitch(switches::kOzoneUseSurfaceless));
    201 }
    202 
    203 }  // namespace ui
    204