// Copyright (c) 2012 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 "base/base_paths.h" #include "base/command_line.h" #include "base/files/file_path.h" #include "base/logging.h" #include "base/mac/foundation_util.h" #include "base/native_library.h" #include "base/path_service.h" #include "base/threading/thread_restrictions.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_context_stub_with_extensions.h" #include "ui/gl/gl_gl_api_implementation.h" #include "ui/gl/gl_implementation.h" #include "ui/gl/gl_osmesa_api_implementation.h" namespace gfx { namespace { const char kOpenGLFrameworkPath[] = "/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL"; } // namespace void GetAllowedGLImplementations(std::vector* impls) { if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableUnsafeES3APIs)) { impls->push_back(kGLImplementationDesktopGLCoreProfile); } impls->push_back(kGLImplementationDesktopGL); impls->push_back(kGLImplementationAppleGL); impls->push_back(kGLImplementationOSMesaGL); } bool InitializeStaticGLBindings(GLImplementation implementation) { // Prevent reinitialization with a different implementation. Once the gpu // unit tests have initialized with kGLImplementationMock, we don't want to // later switch to another GL implementation. DCHECK_EQ(kGLImplementationNone, GetGLImplementation()); // Allow the main thread or another to initialize these bindings // after instituting restrictions on I/O. Going forward they will // likely be used in the browser process on most platforms. The // one-time initialization cost is small, between 2 and 5 ms. base::ThreadRestrictions::ScopedAllowIO allow_io; switch (implementation) { case kGLImplementationOSMesaGL: { // osmesa.so is located in the build directory. This code path is only // valid in a developer build environment. base::FilePath exe_path; if (!PathService::Get(base::FILE_EXE, &exe_path)) { LOG(ERROR) << "PathService::Get failed."; return false; } base::FilePath bundle_path = base::mac::GetAppBundlePath(exe_path); // Some unit test targets depend on osmesa but aren't built as app // bundles. In that case, the .so is next to the executable. if (bundle_path.empty()) bundle_path = exe_path; base::FilePath build_dir_path = bundle_path.DirName(); base::FilePath osmesa_path = build_dir_path.Append("osmesa.so"); // When using OSMesa, just use OSMesaGetProcAddress to find entry points. base::NativeLibrary library = base::LoadNativeLibrary(osmesa_path, NULL); if (!library) { LOG(ERROR) << "osmesa.so not found at " << osmesa_path.value(); return false; } GLGetProcAddressProc get_proc_address = reinterpret_cast( base::GetFunctionPointerFromNativeLibrary( library, "OSMesaGetProcAddress")); if (!get_proc_address) { LOG(ERROR) << "OSMesaGetProcAddress not found."; base::UnloadNativeLibrary(library); return false; } SetGLGetProcAddressProc(get_proc_address); AddGLNativeLibrary(library); SetGLImplementation(kGLImplementationOSMesaGL); InitializeStaticGLBindingsGL(); InitializeStaticGLBindingsOSMESA(); break; } case kGLImplementationDesktopGL: case kGLImplementationDesktopGLCoreProfile: case kGLImplementationAppleGL: { base::NativeLibrary library = base::LoadNativeLibrary( base::FilePath(kOpenGLFrameworkPath), NULL); if (!library) { LOG(ERROR) << "OpenGL framework not found"; return false; } AddGLNativeLibrary(library); SetGLImplementation(implementation); InitializeStaticGLBindingsGL(); break; } case kGLImplementationMockGL: { SetGLImplementation(kGLImplementationMockGL); InitializeStaticGLBindingsGL(); break; } default: return false; } return true; } bool InitializeDynamicGLBindings(GLImplementation implementation, GLContext* context) { switch (implementation) { case kGLImplementationOSMesaGL: case kGLImplementationDesktopGL: case kGLImplementationDesktopGLCoreProfile: case kGLImplementationAppleGL: InitializeDynamicGLBindingsGL(context); break; case kGLImplementationMockGL: if (!context) { scoped_refptr mock_context( new GLContextStubWithExtensions()); mock_context->SetGLVersionString("3.0"); InitializeDynamicGLBindingsGL(mock_context.get()); } else InitializeDynamicGLBindingsGL(context); break; default: return false; } return true; } void InitializeDebugGLBindings() { InitializeDebugGLBindingsGL(); InitializeDebugGLBindingsOSMESA(); } void ClearGLBindings() { ClearGLBindingsGL(); ClearGLBindingsOSMESA(); SetGLImplementation(kGLImplementationNone); UnloadGLNativeLibraries(); } bool GetGLWindowSystemBindingInfo(GLWindowSystemBindingInfo* info) { return false; } } // namespace gfx