1 // Copyright (c) 2012 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/gl/gl_surface.h" 6 7 #include <algorithm> 8 #include <vector> 9 10 #include "base/command_line.h" 11 #include "base/debug/trace_event.h" 12 #include "base/lazy_instance.h" 13 #include "base/logging.h" 14 #include "base/threading/thread_local.h" 15 #include "ui/gl/gl_context.h" 16 #include "ui/gl/gl_implementation.h" 17 #include "ui/gl/gl_switches.h" 18 19 #if defined(USE_X11) 20 #include <X11/Xlib.h> 21 #endif 22 23 namespace gfx { 24 25 namespace { 26 base::LazyInstance<base::ThreadLocalPointer<GLSurface> >::Leaky 27 current_surface_ = LAZY_INSTANCE_INITIALIZER; 28 } // namespace 29 30 // static 31 bool GLSurface::InitializeOneOff() { 32 DCHECK_EQ(kGLImplementationNone, GetGLImplementation()); 33 34 TRACE_EVENT0("gpu", "GLSurface::InitializeOneOff"); 35 36 std::vector<GLImplementation> allowed_impls; 37 GetAllowedGLImplementations(&allowed_impls); 38 DCHECK(!allowed_impls.empty()); 39 40 CommandLine* cmd = CommandLine::ForCurrentProcess(); 41 42 // The default implementation is always the first one in list. 43 GLImplementation impl = allowed_impls[0]; 44 bool fallback_to_osmesa = false; 45 if (cmd->HasSwitch(switches::kOverrideUseGLWithOSMesaForTests)) { 46 impl = kGLImplementationOSMesaGL; 47 } else if (cmd->HasSwitch(switches::kUseGL)) { 48 std::string requested_implementation_name = 49 cmd->GetSwitchValueASCII(switches::kUseGL); 50 if (requested_implementation_name == "any") { 51 fallback_to_osmesa = true; 52 } else if (requested_implementation_name == "swiftshader") { 53 impl = kGLImplementationEGLGLES2; 54 } else { 55 impl = GetNamedGLImplementation(requested_implementation_name); 56 if (std::find(allowed_impls.begin(), 57 allowed_impls.end(), 58 impl) == allowed_impls.end()) { 59 LOG(ERROR) << "Requested GL implementation is not available."; 60 return false; 61 } 62 } 63 } 64 65 bool gpu_service_logging = cmd->HasSwitch(switches::kEnableGPUServiceLogging); 66 bool disable_gl_drawing = cmd->HasSwitch(switches::kDisableGLDrawingForTests); 67 68 return InitializeOneOffImplementation( 69 impl, fallback_to_osmesa, gpu_service_logging, disable_gl_drawing); 70 } 71 72 // static 73 bool GLSurface::InitializeOneOffImplementation(GLImplementation impl, 74 bool fallback_to_osmesa, 75 bool gpu_service_logging, 76 bool disable_gl_drawing) { 77 bool initialized = 78 InitializeStaticGLBindings(impl) && InitializeOneOffInternal(); 79 if (!initialized && fallback_to_osmesa) { 80 ClearGLBindings(); 81 initialized = InitializeStaticGLBindings(kGLImplementationOSMesaGL) && 82 InitializeOneOffInternal(); 83 } 84 if (!initialized) 85 ClearGLBindings(); 86 87 if (initialized) { 88 DVLOG(1) << "Using " 89 << GetGLImplementationName(GetGLImplementation()) 90 << " GL implementation."; 91 if (gpu_service_logging) 92 InitializeDebugGLBindings(); 93 if (disable_gl_drawing) 94 InitializeNullDrawGLBindings(); 95 } 96 return initialized; 97 } 98 99 // static 100 void GLSurface::InitializeOneOffForTests() { 101 DCHECK_EQ(kGLImplementationNone, GetGLImplementation()); 102 103 #if defined(USE_X11) 104 XInitThreads(); 105 #endif 106 107 bool use_osmesa = true; 108 109 // We usually use OSMesa as this works on all bots. The command line can 110 // override this behaviour to use hardware GL. 111 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseGpuInTests)) 112 use_osmesa = false; 113 114 #if defined(OS_ANDROID) 115 // On Android we always use hardware GL. 116 use_osmesa = false; 117 #endif 118 119 std::vector<GLImplementation> allowed_impls; 120 GetAllowedGLImplementations(&allowed_impls); 121 DCHECK(!allowed_impls.empty()); 122 123 GLImplementation impl = allowed_impls[0]; 124 if (use_osmesa) 125 impl = kGLImplementationOSMesaGL; 126 127 DCHECK(!CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseGL)) 128 << "kUseGL has not effect in tests"; 129 130 bool fallback_to_osmesa = false; 131 bool gpu_service_logging = false; 132 bool disable_gl_drawing = true; 133 134 CHECK(InitializeOneOffImplementation( 135 impl, fallback_to_osmesa, gpu_service_logging, disable_gl_drawing)); 136 } 137 138 // static 139 void GLSurface::InitializeOneOffWithMockBindingsForTests() { 140 DCHECK(!CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseGL)) 141 << "kUseGL has not effect in tests"; 142 143 // This method may be called multiple times in the same process to set up 144 // mock bindings in different ways. 145 ClearGLBindings(); 146 147 bool fallback_to_osmesa = false; 148 bool gpu_service_logging = false; 149 bool disable_gl_drawing = false; 150 151 CHECK(InitializeOneOffImplementation(kGLImplementationMockGL, 152 fallback_to_osmesa, 153 gpu_service_logging, 154 disable_gl_drawing)); 155 } 156 157 // static 158 void GLSurface::InitializeDynamicMockBindingsForTests(GLContext* context) { 159 CHECK(InitializeDynamicGLBindings(kGLImplementationMockGL, context)); 160 } 161 162 GLSurface::GLSurface() {} 163 164 bool GLSurface::Initialize() { 165 return true; 166 } 167 168 bool GLSurface::Resize(const gfx::Size& size) { 169 NOTIMPLEMENTED(); 170 return false; 171 } 172 173 bool GLSurface::Recreate() { 174 NOTIMPLEMENTED(); 175 return false; 176 } 177 178 bool GLSurface::DeferDraws() { 179 return false; 180 } 181 182 bool GLSurface::SupportsPostSubBuffer() { 183 return false; 184 } 185 186 unsigned int GLSurface::GetBackingFrameBufferObject() { 187 return 0; 188 } 189 190 bool GLSurface::PostSubBuffer(int x, int y, int width, int height) { 191 return false; 192 } 193 194 bool GLSurface::OnMakeCurrent(GLContext* context) { 195 return true; 196 } 197 198 bool GLSurface::SetBackbufferAllocation(bool allocated) { 199 return true; 200 } 201 202 void GLSurface::SetFrontbufferAllocation(bool allocated) { 203 } 204 205 void* GLSurface::GetShareHandle() { 206 NOTIMPLEMENTED(); 207 return NULL; 208 } 209 210 void* GLSurface::GetDisplay() { 211 NOTIMPLEMENTED(); 212 return NULL; 213 } 214 215 void* GLSurface::GetConfig() { 216 NOTIMPLEMENTED(); 217 return NULL; 218 } 219 220 unsigned GLSurface::GetFormat() { 221 NOTIMPLEMENTED(); 222 return 0; 223 } 224 225 VSyncProvider* GLSurface::GetVSyncProvider() { 226 return NULL; 227 } 228 229 bool GLSurface::ScheduleOverlayPlane(int z_order, 230 OverlayTransform transform, 231 GLImage* image, 232 const Rect& bounds_rect, 233 const RectF& crop_rect) { 234 NOTIMPLEMENTED(); 235 return false; 236 } 237 238 bool GLSurface::IsSurfaceless() const { 239 return false; 240 } 241 242 GLSurface* GLSurface::GetCurrent() { 243 return current_surface_.Pointer()->Get(); 244 } 245 246 GLSurface::~GLSurface() { 247 if (GetCurrent() == this) 248 SetCurrent(NULL); 249 } 250 251 void GLSurface::SetCurrent(GLSurface* surface) { 252 current_surface_.Pointer()->Set(surface); 253 } 254 255 bool GLSurface::ExtensionsContain(const char* c_extensions, const char* name) { 256 DCHECK(name); 257 if (!c_extensions) 258 return false; 259 std::string extensions(c_extensions); 260 extensions += " "; 261 262 std::string delimited_name(name); 263 delimited_name += " "; 264 265 return extensions.find(delimited_name) != std::string::npos; 266 } 267 268 GLSurfaceAdapter::GLSurfaceAdapter(GLSurface* surface) : surface_(surface) {} 269 270 bool GLSurfaceAdapter::Initialize() { 271 return surface_->Initialize(); 272 } 273 274 void GLSurfaceAdapter::Destroy() { 275 surface_->Destroy(); 276 } 277 278 bool GLSurfaceAdapter::Resize(const gfx::Size& size) { 279 return surface_->Resize(size); 280 } 281 282 bool GLSurfaceAdapter::Recreate() { 283 return surface_->Recreate(); 284 } 285 286 bool GLSurfaceAdapter::DeferDraws() { 287 return surface_->DeferDraws(); 288 } 289 290 bool GLSurfaceAdapter::IsOffscreen() { 291 return surface_->IsOffscreen(); 292 } 293 294 bool GLSurfaceAdapter::SwapBuffers() { 295 return surface_->SwapBuffers(); 296 } 297 298 bool GLSurfaceAdapter::PostSubBuffer(int x, int y, int width, int height) { 299 return surface_->PostSubBuffer(x, y, width, height); 300 } 301 302 bool GLSurfaceAdapter::SupportsPostSubBuffer() { 303 return surface_->SupportsPostSubBuffer(); 304 } 305 306 gfx::Size GLSurfaceAdapter::GetSize() { 307 return surface_->GetSize(); 308 } 309 310 void* GLSurfaceAdapter::GetHandle() { 311 return surface_->GetHandle(); 312 } 313 314 unsigned int GLSurfaceAdapter::GetBackingFrameBufferObject() { 315 return surface_->GetBackingFrameBufferObject(); 316 } 317 318 bool GLSurfaceAdapter::OnMakeCurrent(GLContext* context) { 319 return surface_->OnMakeCurrent(context); 320 } 321 322 bool GLSurfaceAdapter::SetBackbufferAllocation(bool allocated) { 323 return surface_->SetBackbufferAllocation(allocated); 324 } 325 326 void GLSurfaceAdapter::SetFrontbufferAllocation(bool allocated) { 327 surface_->SetFrontbufferAllocation(allocated); 328 } 329 330 void* GLSurfaceAdapter::GetShareHandle() { 331 return surface_->GetShareHandle(); 332 } 333 334 void* GLSurfaceAdapter::GetDisplay() { 335 return surface_->GetDisplay(); 336 } 337 338 void* GLSurfaceAdapter::GetConfig() { 339 return surface_->GetConfig(); 340 } 341 342 unsigned GLSurfaceAdapter::GetFormat() { 343 return surface_->GetFormat(); 344 } 345 346 VSyncProvider* GLSurfaceAdapter::GetVSyncProvider() { 347 return surface_->GetVSyncProvider(); 348 } 349 350 bool GLSurfaceAdapter::ScheduleOverlayPlane(int z_order, 351 OverlayTransform transform, 352 GLImage* image, 353 const Rect& bounds_rect, 354 const RectF& crop_rect) { 355 return surface_->ScheduleOverlayPlane( 356 z_order, transform, image, bounds_rect, crop_rect); 357 } 358 359 bool GLSurfaceAdapter::IsSurfaceless() const { 360 return surface_->IsSurfaceless(); 361 } 362 363 GLSurfaceAdapter::~GLSurfaceAdapter() {} 364 365 } // namespace gfx 366