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 <vector> 6 7 #include "base/command_line.h" 8 #include "base/logging.h" 9 #include "base/threading/thread_restrictions.h" 10 #include "ui/gl/gl_bindings.h" 11 #include "ui/gl/gl_egl_api_implementation.h" 12 #include "ui/gl/gl_gl_api_implementation.h" 13 #include "ui/gl/gl_glx_api_implementation.h" 14 #include "ui/gl/gl_implementation.h" 15 #include "ui/gl/gl_implementation_linux.h" 16 #include "ui/gl/gl_osmesa_api_implementation.h" 17 #include "ui/gl/gl_switches.h" 18 19 namespace gfx { 20 namespace { 21 22 // TODO(piman): it should be Desktop GL marshalling from double to float. Today 23 // on native GLES, we do float->double->float. 24 void GL_BINDING_CALL MarshalClearDepthToClearDepthf(GLclampd depth) { 25 glClearDepthf(static_cast<GLclampf>(depth)); 26 } 27 28 void GL_BINDING_CALL MarshalDepthRangeToDepthRangef(GLclampd z_near, 29 GLclampd z_far) { 30 glDepthRangef(static_cast<GLclampf>(z_near), static_cast<GLclampf>(z_far)); 31 } 32 33 } // namespace 34 35 void GetAllowedGLImplementations(std::vector<GLImplementation>* impls) { 36 impls->push_back(kGLImplementationDesktopGL); 37 impls->push_back(kGLImplementationEGLGLES2); 38 impls->push_back(kGLImplementationOSMesaGL); 39 } 40 41 bool InitializeGLBindings(GLImplementation implementation) { 42 // Prevent reinitialization with a different implementation. Once the gpu 43 // unit tests have initialized with kGLImplementationMock, we don't want to 44 // later switch to another GL implementation. 45 if (GetGLImplementation() != kGLImplementationNone) 46 return true; 47 48 // Allow the main thread or another to initialize these bindings 49 // after instituting restrictions on I/O. Going forward they will 50 // likely be used in the browser process on most platforms. The 51 // one-time initialization cost is small, between 2 and 5 ms. 52 base::ThreadRestrictions::ScopedAllowIO allow_io; 53 54 switch (implementation) { 55 case kGLImplementationOSMesaGL: 56 return InitializeGLBindingsOSMesaGL(); 57 case kGLImplementationDesktopGL: { 58 base::NativeLibrary library = NULL; 59 const CommandLine* command_line = CommandLine::ForCurrentProcess(); 60 61 if (command_line->HasSwitch(switches::kTestGLLib)) 62 library = LoadLibrary(command_line->GetSwitchValueASCII( 63 switches::kTestGLLib).c_str()); 64 65 if (!library) { 66 #if defined(OS_OPENBSD) 67 library = LoadLibrary("libGL.so"); 68 #else 69 library = LoadLibrary("libGL.so.1"); 70 #endif 71 } 72 73 if (!library) 74 return false; 75 76 GLGetProcAddressProc get_proc_address = 77 reinterpret_cast<GLGetProcAddressProc>( 78 base::GetFunctionPointerFromNativeLibrary( 79 library, "glXGetProcAddress")); 80 if (!get_proc_address) { 81 LOG(ERROR) << "glxGetProcAddress not found."; 82 base::UnloadNativeLibrary(library); 83 return false; 84 } 85 86 SetGLGetProcAddressProc(get_proc_address); 87 AddGLNativeLibrary(library); 88 SetGLImplementation(kGLImplementationDesktopGL); 89 90 InitializeGLBindingsGL(); 91 InitializeGLBindingsGLX(); 92 break; 93 } 94 case kGLImplementationEGLGLES2: { 95 base::NativeLibrary gles_library = LoadLibrary("libGLESv2.so.2"); 96 if (!gles_library) 97 return false; 98 base::NativeLibrary egl_library = LoadLibrary("libEGL.so.1"); 99 if (!egl_library) { 100 base::UnloadNativeLibrary(gles_library); 101 return false; 102 } 103 104 GLGetProcAddressProc get_proc_address = 105 reinterpret_cast<GLGetProcAddressProc>( 106 base::GetFunctionPointerFromNativeLibrary( 107 egl_library, "eglGetProcAddress")); 108 if (!get_proc_address) { 109 LOG(ERROR) << "eglGetProcAddress not found."; 110 base::UnloadNativeLibrary(egl_library); 111 base::UnloadNativeLibrary(gles_library); 112 return false; 113 } 114 115 SetGLGetProcAddressProc(get_proc_address); 116 AddGLNativeLibrary(egl_library); 117 AddGLNativeLibrary(gles_library); 118 SetGLImplementation(kGLImplementationEGLGLES2); 119 120 InitializeGLBindingsGL(); 121 InitializeGLBindingsEGL(); 122 123 // These two functions take single precision float rather than double 124 // precision float parameters in GLES. 125 ::gfx::g_driver_gl.fn.glClearDepthFn = MarshalClearDepthToClearDepthf; 126 ::gfx::g_driver_gl.fn.glDepthRangeFn = MarshalDepthRangeToDepthRangef; 127 break; 128 } 129 case kGLImplementationMockGL: { 130 SetGLGetProcAddressProc(GetMockGLProcAddress); 131 SetGLImplementation(kGLImplementationMockGL); 132 InitializeGLBindingsGL(); 133 break; 134 } 135 default: 136 return false; 137 } 138 139 140 return true; 141 } 142 143 bool InitializeGLExtensionBindings(GLImplementation implementation, 144 GLContext* context) { 145 switch (implementation) { 146 case kGLImplementationOSMesaGL: 147 InitializeGLExtensionBindingsGL(context); 148 InitializeGLExtensionBindingsOSMESA(context); 149 break; 150 case kGLImplementationDesktopGL: 151 InitializeGLExtensionBindingsGL(context); 152 InitializeGLExtensionBindingsGLX(context); 153 break; 154 case kGLImplementationEGLGLES2: 155 InitializeGLExtensionBindingsGL(context); 156 InitializeGLExtensionBindingsEGL(context); 157 break; 158 case kGLImplementationMockGL: 159 InitializeGLExtensionBindingsGL(context); 160 break; 161 default: 162 return false; 163 } 164 165 return true; 166 } 167 168 void InitializeDebugGLBindings() { 169 InitializeDebugGLBindingsEGL(); 170 InitializeDebugGLBindingsGL(); 171 InitializeDebugGLBindingsGLX(); 172 InitializeDebugGLBindingsOSMESA(); 173 } 174 175 void ClearGLBindings() { 176 ClearGLBindingsEGL(); 177 ClearGLBindingsGL(); 178 ClearGLBindingsGLX(); 179 ClearGLBindingsOSMESA(); 180 SetGLImplementation(kGLImplementationNone); 181 182 UnloadGLNativeLibraries(); 183 } 184 185 bool GetGLWindowSystemBindingInfo(GLWindowSystemBindingInfo* info) { 186 switch (GetGLImplementation()) { 187 case kGLImplementationDesktopGL: 188 return GetGLWindowSystemBindingInfoGLX(info); 189 case kGLImplementationEGLGLES2: 190 return GetGLWindowSystemBindingInfoEGL(info); 191 default: 192 return false; 193 } 194 return false; 195 } 196 197 } // namespace gfx 198