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