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