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 "base/base_paths.h" 6#include "base/files/file_path.h" 7#include "base/logging.h" 8#include "base/mac/foundation_util.h" 9#include "base/native_library.h" 10#include "base/path_service.h" 11#include "base/threading/thread_restrictions.h" 12#include "ui/gl/gl_bindings.h" 13#include "ui/gl/gl_context_stub_with_extensions.h" 14#include "ui/gl/gl_gl_api_implementation.h" 15#include "ui/gl/gl_implementation.h" 16#include "ui/gl/gl_osmesa_api_implementation.h" 17 18namespace gfx { 19namespace { 20const char kOpenGLFrameworkPath[] = 21 "/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL"; 22} // namespace 23 24void GetAllowedGLImplementations(std::vector<GLImplementation>* impls) { 25 impls->push_back(kGLImplementationDesktopGL); 26 impls->push_back(kGLImplementationAppleGL); 27 impls->push_back(kGLImplementationOSMesaGL); 28} 29 30bool InitializeStaticGLBindings(GLImplementation implementation) { 31 // Prevent reinitialization with a different implementation. Once the gpu 32 // unit tests have initialized with kGLImplementationMock, we don't want to 33 // later switch to another GL implementation. 34 DCHECK_EQ(kGLImplementationNone, GetGLImplementation()); 35 36 // Allow the main thread or another to initialize these bindings 37 // after instituting restrictions on I/O. Going forward they will 38 // likely be used in the browser process on most platforms. The 39 // one-time initialization cost is small, between 2 and 5 ms. 40 base::ThreadRestrictions::ScopedAllowIO allow_io; 41 42 switch (implementation) { 43 case kGLImplementationOSMesaGL: { 44 // osmesa.so is located in the build directory. This code path is only 45 // valid in a developer build environment. 46 base::FilePath exe_path; 47 if (!PathService::Get(base::FILE_EXE, &exe_path)) { 48 LOG(ERROR) << "PathService::Get failed."; 49 return false; 50 } 51 base::FilePath bundle_path = base::mac::GetAppBundlePath(exe_path); 52 // Some unit test targets depend on osmesa but aren't built as app 53 // bundles. In that case, the .so is next to the executable. 54 if (bundle_path.empty()) 55 bundle_path = exe_path; 56 base::FilePath build_dir_path = bundle_path.DirName(); 57 base::FilePath osmesa_path = build_dir_path.Append("osmesa.so"); 58 59 // When using OSMesa, just use OSMesaGetProcAddress to find entry points. 60 base::NativeLibrary library = base::LoadNativeLibrary(osmesa_path, NULL); 61 if (!library) { 62 LOG(ERROR) << "osmesa.so not found at " << osmesa_path.value(); 63 return false; 64 } 65 66 GLGetProcAddressProc get_proc_address = 67 reinterpret_cast<GLGetProcAddressProc>( 68 base::GetFunctionPointerFromNativeLibrary( 69 library, "OSMesaGetProcAddress")); 70 if (!get_proc_address) { 71 LOG(ERROR) << "OSMesaGetProcAddress not found."; 72 base::UnloadNativeLibrary(library); 73 return false; 74 } 75 76 SetGLGetProcAddressProc(get_proc_address); 77 AddGLNativeLibrary(library); 78 SetGLImplementation(kGLImplementationOSMesaGL); 79 80 InitializeStaticGLBindingsGL(); 81 InitializeStaticGLBindingsOSMESA(); 82 break; 83 } 84 case kGLImplementationDesktopGL: 85 case kGLImplementationAppleGL: { 86 base::NativeLibrary library = base::LoadNativeLibrary( 87 base::FilePath(kOpenGLFrameworkPath), NULL); 88 if (!library) { 89 LOG(ERROR) << "OpenGL framework not found"; 90 return false; 91 } 92 93 AddGLNativeLibrary(library); 94 SetGLImplementation(implementation); 95 96 InitializeStaticGLBindingsGL(); 97 break; 98 } 99 case kGLImplementationMockGL: { 100 SetGLImplementation(kGLImplementationMockGL); 101 InitializeStaticGLBindingsGL(); 102 break; 103 } 104 default: 105 return false; 106 } 107 108 return true; 109} 110 111bool InitializeDynamicGLBindings(GLImplementation implementation, 112 GLContext* context) { 113 switch (implementation) { 114 case kGLImplementationOSMesaGL: 115 InitializeDynamicGLBindingsGL(context); 116 InitializeDynamicGLBindingsOSMESA(context); 117 break; 118 case kGLImplementationDesktopGL: 119 case kGLImplementationAppleGL: 120 InitializeDynamicGLBindingsGL(context); 121 break; 122 case kGLImplementationMockGL: 123 if (!context) { 124 scoped_refptr<GLContextStubWithExtensions> mock_context( 125 new GLContextStubWithExtensions()); 126 mock_context->SetGLVersionString("3.0"); 127 InitializeDynamicGLBindingsGL(mock_context.get()); 128 } else 129 InitializeDynamicGLBindingsGL(context); 130 break; 131 default: 132 return false; 133 } 134 135 return true; 136} 137 138void InitializeDebugGLBindings() { 139 InitializeDebugGLBindingsGL(); 140 InitializeDebugGLBindingsOSMESA(); 141} 142 143void ClearGLBindings() { 144 ClearGLBindingsGL(); 145 ClearGLBindingsOSMESA(); 146 SetGLImplementation(kGLImplementationNone); 147 148 UnloadGLNativeLibraries(); 149} 150 151bool GetGLWindowSystemBindingInfo(GLWindowSystemBindingInfo* info) { 152 return false; 153} 154 155} // namespace gfx 156