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 23namespace gfx { 24 25namespace { 26base::LazyInstance<base::ThreadLocalPointer<GLSurface> >::Leaky 27 current_surface_ = LAZY_INSTANCE_INITIALIZER; 28} // namespace 29 30// static 31bool 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 73bool 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 100void 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 139void 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 158void GLSurface::InitializeDynamicMockBindingsForTests(GLContext* context) { 159 CHECK(InitializeDynamicGLBindings(kGLImplementationMockGL, context)); 160} 161 162GLSurface::GLSurface() {} 163 164bool GLSurface::Initialize() { 165 return true; 166} 167 168bool GLSurface::Resize(const gfx::Size& size) { 169 NOTIMPLEMENTED(); 170 return false; 171} 172 173bool GLSurface::Recreate() { 174 NOTIMPLEMENTED(); 175 return false; 176} 177 178bool GLSurface::DeferDraws() { 179 return false; 180} 181 182bool GLSurface::SupportsPostSubBuffer() { 183 return false; 184} 185 186unsigned int GLSurface::GetBackingFrameBufferObject() { 187 return 0; 188} 189 190bool GLSurface::PostSubBuffer(int x, int y, int width, int height) { 191 return false; 192} 193 194bool GLSurface::OnMakeCurrent(GLContext* context) { 195 return true; 196} 197 198bool GLSurface::SetBackbufferAllocation(bool allocated) { 199 return true; 200} 201 202void GLSurface::SetFrontbufferAllocation(bool allocated) { 203} 204 205void* GLSurface::GetShareHandle() { 206 NOTIMPLEMENTED(); 207 return NULL; 208} 209 210void* GLSurface::GetDisplay() { 211 NOTIMPLEMENTED(); 212 return NULL; 213} 214 215void* GLSurface::GetConfig() { 216 NOTIMPLEMENTED(); 217 return NULL; 218} 219 220unsigned GLSurface::GetFormat() { 221 NOTIMPLEMENTED(); 222 return 0; 223} 224 225VSyncProvider* GLSurface::GetVSyncProvider() { 226 return NULL; 227} 228 229bool 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 238bool GLSurface::IsSurfaceless() const { 239 return false; 240} 241 242GLSurface* GLSurface::GetCurrent() { 243 return current_surface_.Pointer()->Get(); 244} 245 246GLSurface::~GLSurface() { 247 if (GetCurrent() == this) 248 SetCurrent(NULL); 249} 250 251void GLSurface::SetCurrent(GLSurface* surface) { 252 current_surface_.Pointer()->Set(surface); 253} 254 255bool 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 268GLSurfaceAdapter::GLSurfaceAdapter(GLSurface* surface) : surface_(surface) {} 269 270bool GLSurfaceAdapter::Initialize() { 271 return surface_->Initialize(); 272} 273 274void GLSurfaceAdapter::Destroy() { 275 surface_->Destroy(); 276} 277 278bool GLSurfaceAdapter::Resize(const gfx::Size& size) { 279 return surface_->Resize(size); 280} 281 282bool GLSurfaceAdapter::Recreate() { 283 return surface_->Recreate(); 284} 285 286bool GLSurfaceAdapter::DeferDraws() { 287 return surface_->DeferDraws(); 288} 289 290bool GLSurfaceAdapter::IsOffscreen() { 291 return surface_->IsOffscreen(); 292} 293 294bool GLSurfaceAdapter::SwapBuffers() { 295 return surface_->SwapBuffers(); 296} 297 298bool GLSurfaceAdapter::PostSubBuffer(int x, int y, int width, int height) { 299 return surface_->PostSubBuffer(x, y, width, height); 300} 301 302bool GLSurfaceAdapter::SupportsPostSubBuffer() { 303 return surface_->SupportsPostSubBuffer(); 304} 305 306gfx::Size GLSurfaceAdapter::GetSize() { 307 return surface_->GetSize(); 308} 309 310void* GLSurfaceAdapter::GetHandle() { 311 return surface_->GetHandle(); 312} 313 314unsigned int GLSurfaceAdapter::GetBackingFrameBufferObject() { 315 return surface_->GetBackingFrameBufferObject(); 316} 317 318bool GLSurfaceAdapter::OnMakeCurrent(GLContext* context) { 319 return surface_->OnMakeCurrent(context); 320} 321 322bool GLSurfaceAdapter::SetBackbufferAllocation(bool allocated) { 323 return surface_->SetBackbufferAllocation(allocated); 324} 325 326void GLSurfaceAdapter::SetFrontbufferAllocation(bool allocated) { 327 surface_->SetFrontbufferAllocation(allocated); 328} 329 330void* GLSurfaceAdapter::GetShareHandle() { 331 return surface_->GetShareHandle(); 332} 333 334void* GLSurfaceAdapter::GetDisplay() { 335 return surface_->GetDisplay(); 336} 337 338void* GLSurfaceAdapter::GetConfig() { 339 return surface_->GetConfig(); 340} 341 342unsigned GLSurfaceAdapter::GetFormat() { 343 return surface_->GetFormat(); 344} 345 346VSyncProvider* GLSurfaceAdapter::GetVSyncProvider() { 347 return surface_->GetVSyncProvider(); 348} 349 350bool 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 359bool GLSurfaceAdapter::IsSurfaceless() const { 360 return surface_->IsSurfaceless(); 361} 362 363GLSurfaceAdapter::~GLSurfaceAdapter() {} 364 365} // namespace gfx 366