// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "ui/gfx/gl/gl_implementation.h" #include #include #include "base/at_exit.h" #include "base/command_line.h" #include "base/logging.h" #include "ui/gfx/gl/gl_switches.h" namespace gfx { const char kGLImplementationDesktopName[] = "desktop"; const char kGLImplementationOSMesaName[] = "osmesa"; const char kGLImplementationEGLName[] = "egl"; const char kGLImplementationMockName[] = "mock"; namespace { const struct { const char* name; GLImplementation implementation; } kGLImplementationNamePairs[] = { { kGLImplementationDesktopName, kGLImplementationDesktopGL }, { kGLImplementationOSMesaName, kGLImplementationOSMesaGL }, { kGLImplementationEGLName, kGLImplementationEGLGLES2 }, { kGLImplementationMockName, kGLImplementationMockGL } }; typedef std::vector LibraryArray; GLImplementation g_gl_implementation = kGLImplementationNone; LibraryArray* g_libraries; GLGetProcAddressProc g_get_proc_address; void CleanupNativeLibraries(void* unused) { if (g_libraries) { for (LibraryArray::iterator it = g_libraries->begin(); it != g_libraries->end(); ++it) { base::UnloadNativeLibrary(*it); } delete g_libraries; g_libraries = NULL; } } } GLImplementation GetNamedGLImplementation(const std::string& name) { for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kGLImplementationNamePairs); ++i) { if (name == kGLImplementationNamePairs[i].name) return kGLImplementationNamePairs[i].implementation; } return kGLImplementationNone; } const char* GetGLImplementationName(GLImplementation implementation) { for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kGLImplementationNamePairs); ++i) { if (implementation == kGLImplementationNamePairs[i].implementation) return kGLImplementationNamePairs[i].name; } return "unknown"; } bool InitializeRequestedGLBindings( const GLImplementation* allowed_implementations_begin, const GLImplementation* allowed_implementations_end, GLImplementation default_implementation) { if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseGL)) { std::string requested_implementation_name = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switches::kUseGL); GLImplementation requested_implementation = GetNamedGLImplementation(requested_implementation_name); if (std::find(allowed_implementations_begin, allowed_implementations_end, requested_implementation) == allowed_implementations_end) { LOG(ERROR) << "Requested GL implementation is not available."; return false; } InitializeGLBindings(requested_implementation); } else { InitializeGLBindings(default_implementation); } if (GetGLImplementation() == kGLImplementationNone) { LOG(ERROR) << "Could not initialize GL."; return false; } else { LOG(INFO) << "Using " << GetGLImplementationName(GetGLImplementation()) << " GL implementation."; return true; } } void SetGLImplementation(GLImplementation implementation) { g_gl_implementation = implementation; } GLImplementation GetGLImplementation() { return g_gl_implementation; } void AddGLNativeLibrary(base::NativeLibrary library) { DCHECK(library); if (!g_libraries) { g_libraries = new LibraryArray; base::AtExitManager::RegisterCallback(CleanupNativeLibraries, NULL); } g_libraries->push_back(library); } void SetGLGetProcAddressProc(GLGetProcAddressProc proc) { DCHECK(proc); g_get_proc_address = proc; } void* GetGLProcAddress(const char* name) { DCHECK(g_gl_implementation != kGLImplementationNone); if (g_libraries) { for (size_t i = 0; i < g_libraries->size(); ++i) { void* proc = base::GetFunctionPointerFromNativeLibrary((*g_libraries)[i], name); if (proc) return proc; } } if (g_get_proc_address) { void* proc = g_get_proc_address(name); if (proc) return proc; } return NULL; } } // namespace gfx