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 23namespace ui { 24namespace { 25 26class 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 69GbmSurfaceFactory::GbmSurfaceFactory(bool allow_surfaceless) 70 : DriSurfaceFactory(NULL, NULL, NULL), 71 device_(NULL), 72 allow_surfaceless_(allow_surfaceless) { 73} 74 75GbmSurfaceFactory::~GbmSurfaceFactory() {} 76 77void 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 88intptr_t GbmSurfaceFactory::GetNativeDisplay() { 89 DCHECK(state_ == INITIALIZED); 90 return reinterpret_cast<intptr_t>(device_); 91} 92 93const 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 109bool 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 148scoped_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 161scoped_ptr<SurfaceOzoneEGL> 162GbmSurfaceFactory::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 171scoped_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 182OverlayCandidatesOzone* GbmSurfaceFactory::GetOverlayCandidates( 183 gfx::AcceleratedWidget w) { 184 if (CommandLine::ForCurrentProcess()->HasSwitch( 185 switches::kOzoneTestSingleOverlaySupport)) 186 return new SingleOverlay(); 187 return NULL; 188} 189 190bool 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 215bool GbmSurfaceFactory::CanShowPrimaryPlaneAsOverlay() { 216 return allow_surfaceless_; 217} 218 219DriWindowDelegate* 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