15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base_paths.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/mac/foundation_util.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/native_library.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_restrictions.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_bindings.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gl/gl_context_stub_with_extensions.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_gl_api_implementation.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_implementation.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_osmesa_api_implementation.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx { 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kOpenGLFrameworkPath[] = 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL"; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetAllowedGLImplementations(std::vector<GLImplementation>* impls) { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) impls->push_back(kGLImplementationDesktopGL); 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) impls->push_back(kGLImplementationAppleGL); 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) impls->push_back(kGLImplementationOSMesaGL); 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool InitializeStaticGLBindings(GLImplementation implementation) { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Prevent reinitialization with a different implementation. Once the gpu 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // unit tests have initialized with kGLImplementationMock, we don't want to 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // later switch to another GL implementation. 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(kGLImplementationNone, GetGLImplementation()); 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Allow the main thread or another to initialize these bindings 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // after instituting restrictions on I/O. Going forward they will 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // likely be used in the browser process on most platforms. The 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // one-time initialization cost is small, between 2 and 5 ms. 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ThreadRestrictions::ScopedAllowIO allow_io; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (implementation) { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kGLImplementationOSMesaGL: { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // osmesa.so is located in the build directory. This code path is only 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // valid in a developer build environment. 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath exe_path; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!PathService::Get(base::FILE_EXE, &exe_path)) { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "PathService::Get failed."; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath bundle_path = base::mac::GetAppBundlePath(exe_path); 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Some unit test targets depend on osmesa but aren't built as app 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // bundles. In that case, the .so is next to the executable. 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (bundle_path.empty()) 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bundle_path = exe_path; 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath build_dir_path = bundle_path.DirName(); 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath osmesa_path = build_dir_path.Append("osmesa.so"); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When using OSMesa, just use OSMesaGetProcAddress to find entry points. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::NativeLibrary library = base::LoadNativeLibrary(osmesa_path, NULL); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!library) { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "osmesa.so not found at " << osmesa_path.value(); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLGetProcAddressProc get_proc_address = 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<GLGetProcAddressProc>( 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::GetFunctionPointerFromNativeLibrary( 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) library, "OSMesaGetProcAddress")); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!get_proc_address) { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "OSMesaGetProcAddress not found."; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::UnloadNativeLibrary(library); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetGLGetProcAddressProc(get_proc_address); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddGLNativeLibrary(library); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetGLImplementation(kGLImplementationOSMesaGL); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) InitializeStaticGLBindingsGL(); 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) InitializeStaticGLBindingsOSMESA(); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kGLImplementationDesktopGL: 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kGLImplementationAppleGL: { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::NativeLibrary library = base::LoadNativeLibrary( 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath(kOpenGLFrameworkPath), NULL); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!library) { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "OpenGL framework not found"; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddGLNativeLibrary(library); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetGLImplementation(implementation); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) InitializeStaticGLBindingsGL(); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kGLImplementationMockGL: { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetGLImplementation(kGLImplementationMockGL); 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) InitializeStaticGLBindingsGL(); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool InitializeDynamicGLBindings(GLImplementation implementation, 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLContext* context) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (implementation) { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kGLImplementationOSMesaGL: 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) InitializeDynamicGLBindingsGL(context); 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) InitializeDynamicGLBindingsOSMESA(context); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kGLImplementationDesktopGL: 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kGLImplementationAppleGL: 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) InitializeDynamicGLBindingsGL(context); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kGLImplementationMockGL: 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!context) { 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<GLContextStubWithExtensions> mock_context( 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new GLContextStubWithExtensions()); 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mock_context->SetGLVersionString("3.0"); 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) InitializeDynamicGLBindingsGL(mock_context.get()); 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) InitializeDynamicGLBindingsGL(context); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InitializeDebugGLBindings() { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitializeDebugGLBindingsGL(); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitializeDebugGLBindingsOSMESA(); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClearGLBindings() { 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClearGLBindingsGL(); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClearGLBindingsOSMESA(); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetGLImplementation(kGLImplementationNone); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UnloadGLNativeLibraries(); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool GetGLWindowSystemBindingInfo(GLWindowSystemBindingInfo* info) { 152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace gfx 156