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/gbm_surface_factory.h"
      6 
      7 #include <gbm.h>
      8 
      9 #include "base/command_line.h"
     10 #include "base/files/file_path.h"
     11 #include "third_party/khronos/EGL/egl.h"
     12 #include "ui/ozone/platform/dri/dri_window_delegate_impl.h"
     13 #include "ui/ozone/platform/dri/dri_window_delegate_manager.h"
     14 #include "ui/ozone/platform/dri/gbm_buffer.h"
     15 #include "ui/ozone/platform/dri/gbm_surface.h"
     16 #include "ui/ozone/platform/dri/gbm_surfaceless.h"
     17 #include "ui/ozone/platform/dri/screen_manager.h"
     18 #include "ui/ozone/public/native_pixmap.h"
     19 #include "ui/ozone/public/overlay_candidates_ozone.h"
     20 #include "ui/ozone/public/ozone_switches.h"
     21 #include "ui/ozone/public/surface_ozone_egl.h"
     22 
     23 namespace ui {
     24 namespace {
     25 
     26 class SingleOverlay : public OverlayCandidatesOzone {
     27  public:
     28   SingleOverlay() {}
     29   virtual ~SingleOverlay() {}
     30 
     31   virtual void CheckOverlaySupport(
     32       OverlaySurfaceCandidateList* candidates) OVERRIDE {
     33     if (candidates->size() == 2) {
     34       OverlayCandidatesOzone::OverlaySurfaceCandidate* first =
     35           &(*candidates)[0];
     36       OverlayCandidatesOzone::OverlaySurfaceCandidate* second =
     37           &(*candidates)[1];
     38       OverlayCandidatesOzone::OverlaySurfaceCandidate* overlay;
     39       if (first->plane_z_order == 0) {
     40         overlay = second;
     41       } else if (second->plane_z_order == 0) {
     42         overlay = first;
     43       } else {
     44         NOTREACHED();
     45         return;
     46       }
     47       if (overlay->plane_z_order > 0 &&
     48           IsTransformSupported(overlay->transform)) {
     49         overlay->overlay_handled = true;
     50       }
     51     }
     52   }
     53 
     54  private:
     55   bool IsTransformSupported(gfx::OverlayTransform transform) {
     56     switch (transform) {
     57       case gfx::OVERLAY_TRANSFORM_NONE:
     58         return true;
     59       default:
     60         return false;
     61     }
     62   }
     63 
     64   DISALLOW_COPY_AND_ASSIGN(SingleOverlay);
     65 };
     66 
     67 }  // namespace
     68 
     69 GbmSurfaceFactory::GbmSurfaceFactory(bool allow_surfaceless)
     70     : DriSurfaceFactory(NULL, NULL, NULL),
     71       device_(NULL),
     72       allow_surfaceless_(allow_surfaceless) {
     73 }
     74 
     75 GbmSurfaceFactory::~GbmSurfaceFactory() {}
     76 
     77 void GbmSurfaceFactory::InitializeGpu(
     78     DriWrapper* dri,
     79     gbm_device* device,
     80     ScreenManager* screen_manager,
     81     DriWindowDelegateManager* window_manager) {
     82   drm_ = dri;
     83   device_ = device;
     84   screen_manager_ = screen_manager;
     85   window_manager_ = window_manager;
     86 }
     87 
     88 intptr_t GbmSurfaceFactory::GetNativeDisplay() {
     89   DCHECK(state_ == INITIALIZED);
     90   return reinterpret_cast<intptr_t>(device_);
     91 }
     92 
     93 const int32* GbmSurfaceFactory::GetEGLSurfaceProperties(
     94     const int32* desired_list) {
     95   static const int32 kConfigAttribs[] = {
     96     EGL_BUFFER_SIZE, 32,
     97     EGL_ALPHA_SIZE, 8,
     98     EGL_BLUE_SIZE, 8,
     99     EGL_GREEN_SIZE, 8,
    100     EGL_RED_SIZE, 8,
    101     EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
    102     EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
    103     EGL_NONE
    104   };
    105 
    106   return kConfigAttribs;
    107 }
    108 
    109 bool GbmSurfaceFactory::LoadEGLGLES2Bindings(
    110       AddGLLibraryCallback add_gl_library,
    111       SetGLGetProcAddressProcCallback set_gl_get_proc_address) {
    112   base::NativeLibraryLoadError error;
    113   base::NativeLibrary gles_library = base::LoadNativeLibrary(
    114       base::FilePath("libGLESv2.so.2"),
    115       &error);
    116   if (!gles_library) {
    117     LOG(WARNING) << "Failed to load GLES library: " << error.ToString();
    118     return false;
    119   }
    120 
    121   base::NativeLibrary egl_library = base::LoadNativeLibrary(
    122       base::FilePath("libEGL.so.1"),
    123       &error);
    124   if (!egl_library) {
    125     LOG(WARNING) << "Failed to load EGL library: " << error.ToString();
    126     base::UnloadNativeLibrary(gles_library);
    127     return false;
    128   }
    129 
    130   GLGetProcAddressProc get_proc_address =
    131       reinterpret_cast<GLGetProcAddressProc>(
    132           base::GetFunctionPointerFromNativeLibrary(
    133               egl_library, "eglGetProcAddress"));
    134   if (!get_proc_address) {
    135     LOG(ERROR) << "eglGetProcAddress not found.";
    136     base::UnloadNativeLibrary(egl_library);
    137     base::UnloadNativeLibrary(gles_library);
    138     return false;
    139   }
    140 
    141   set_gl_get_proc_address.Run(get_proc_address);
    142   add_gl_library.Run(egl_library);
    143   add_gl_library.Run(gles_library);
    144 
    145   return true;
    146 }
    147 
    148 scoped_ptr<SurfaceOzoneEGL> GbmSurfaceFactory::CreateEGLSurfaceForWidget(
    149     gfx::AcceleratedWidget widget) {
    150   DCHECK(state_ == INITIALIZED);
    151 
    152   DriWindowDelegate* delegate = GetOrCreateWindowDelegate(widget);
    153 
    154   scoped_ptr<GbmSurface> surface(new GbmSurface(delegate, device_, drm_));
    155   if (!surface->Initialize())
    156     return scoped_ptr<SurfaceOzoneEGL>();
    157 
    158   return surface.PassAs<SurfaceOzoneEGL>();
    159 }
    160 
    161 scoped_ptr<SurfaceOzoneEGL>
    162 GbmSurfaceFactory::CreateSurfacelessEGLSurfaceForWidget(
    163     gfx::AcceleratedWidget widget) {
    164   if (!allow_surfaceless_)
    165     return scoped_ptr<SurfaceOzoneEGL>();
    166 
    167   DriWindowDelegate* delegate = GetOrCreateWindowDelegate(widget);
    168   return scoped_ptr<SurfaceOzoneEGL>(new GbmSurfaceless(delegate));
    169 }
    170 
    171 scoped_refptr<ui::NativePixmap> GbmSurfaceFactory::CreateNativePixmap(
    172     gfx::Size size,
    173     BufferFormat format) {
    174   scoped_refptr<GbmBuffer> buffer = GbmBuffer::CreateBuffer(
    175       drm_, device_, format, size, true);
    176   if (!buffer.get())
    177     return NULL;
    178 
    179   return scoped_refptr<GbmPixmap>(new GbmPixmap(buffer));
    180 }
    181 
    182 OverlayCandidatesOzone* GbmSurfaceFactory::GetOverlayCandidates(
    183     gfx::AcceleratedWidget w) {
    184   if (CommandLine::ForCurrentProcess()->HasSwitch(
    185           switches::kOzoneTestSingleOverlaySupport))
    186     return new SingleOverlay();
    187   return NULL;
    188 }
    189 
    190 bool GbmSurfaceFactory::ScheduleOverlayPlane(
    191     gfx::AcceleratedWidget widget,
    192     int plane_z_order,
    193     gfx::OverlayTransform plane_transform,
    194     scoped_refptr<NativePixmap> buffer,
    195     const gfx::Rect& display_bounds,
    196     const gfx::RectF& crop_rect) {
    197   scoped_refptr<GbmPixmap> pixmap = static_cast<GbmPixmap*>(buffer.get());
    198   if (!pixmap.get()) {
    199     LOG(ERROR) << "ScheduleOverlayPlane passed NULL buffer.";
    200     return false;
    201   }
    202   HardwareDisplayController* hdc =
    203       window_manager_->GetWindowDelegate(widget)->GetController();
    204   if (!hdc)
    205     return true;
    206 
    207   hdc->QueueOverlayPlane(OverlayPlane(pixmap->buffer(),
    208                                       plane_z_order,
    209                                       plane_transform,
    210                                       display_bounds,
    211                                       crop_rect));
    212   return true;
    213 }
    214 
    215 bool GbmSurfaceFactory::CanShowPrimaryPlaneAsOverlay() {
    216   return allow_surfaceless_;
    217 }
    218 
    219 DriWindowDelegate* GbmSurfaceFactory::GetOrCreateWindowDelegate(
    220     gfx::AcceleratedWidget widget) {
    221   if (!window_manager_->HasWindowDelegate(widget)) {
    222     scoped_ptr<DriWindowDelegate> delegate(
    223         new DriWindowDelegateImpl(widget, screen_manager_));
    224     delegate->Initialize();
    225     window_manager_->AddWindowDelegate(widget, delegate.Pass());
    226   }
    227 
    228   return window_manager_->GetWindowDelegate(widget);
    229 }
    230 
    231 }  // namespace ui
    232