gl_implementation_win.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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/at_exit.h" 8#include "base/base_paths.h" 9#include "base/bind.h" 10#include "base/command_line.h" 11#include "base/file_path.h" 12#include "base/logging.h" 13#include "base/native_library.h" 14#include "base/path_service.h" 15#include "base/stringprintf.h" 16#include "base/threading/thread_restrictions.h" 17#include "ui/gl/gl_bindings.h" 18#include "ui/gl/gl_egl_api_implementation.h" 19#include "ui/gl/gl_gl_api_implementation.h" 20#include "ui/gl/gl_implementation.h" 21#include "ui/gl/gl_osmesa_api_implementation.h" 22#include "ui/gl/gl_wgl_api_implementation.h" 23 24#if defined(ENABLE_SWIFTSHADER) 25#include "software_renderer.h" 26#endif 27 28namespace gfx { 29 30namespace { 31 32// This is the D3DX_SDK_VERSION for the last 'separate' DirectX SDK which 33// is from June 2010. Since June 2012 Microsoft includes DirectX in the regular 34// Windows SDK and the D3DX library has been deprecated. 35const int kPinnedD3DXVersion = 43; 36 37void GL_BINDING_CALL MarshalClearDepthToClearDepthf(GLclampd depth) { 38 glClearDepthf(static_cast<GLclampf>(depth)); 39} 40 41void GL_BINDING_CALL MarshalDepthRangeToDepthRangef(GLclampd z_near, 42 GLclampd z_far) { 43 glDepthRangef(static_cast<GLclampf>(z_near), static_cast<GLclampf>(z_far)); 44} 45 46bool LoadD3DXLibrary(const FilePath& module_path, 47 const FilePath::StringType& name) { 48 base::NativeLibrary library = base::LoadNativeLibrary(FilePath(name), NULL); 49 if (!library) { 50 library = base::LoadNativeLibrary(module_path.Append(name), NULL); 51 if (!library) { 52 DVLOG(1) << name << " not found."; 53 return false; 54 } 55 } 56 return true; 57} 58 59} // namespace 60 61void GetAllowedGLImplementations(std::vector<GLImplementation>* impls) { 62 impls->push_back(kGLImplementationEGLGLES2); 63 impls->push_back(kGLImplementationDesktopGL); 64 impls->push_back(kGLImplementationOSMesaGL); 65} 66 67bool InitializeGLBindings(GLImplementation implementation) { 68 // Prevent reinitialization with a different implementation. Once the gpu 69 // unit tests have initialized with kGLImplementationMock, we don't want to 70 // later switch to another GL implementation. 71 if (GetGLImplementation() != kGLImplementationNone) 72 return true; 73 74 // Allow the main thread or another to initialize these bindings 75 // after instituting restrictions on I/O. Going forward they will 76 // likely be used in the browser process on most platforms. The 77 // one-time initialization cost is small, between 2 and 5 ms. 78 base::ThreadRestrictions::ScopedAllowIO allow_io; 79 80 switch (implementation) { 81 case kGLImplementationOSMesaGL: { 82 FilePath module_path; 83 if (!PathService::Get(base::DIR_MODULE, &module_path)) { 84 LOG(ERROR) << "PathService::Get failed."; 85 return false; 86 } 87 88 base::NativeLibrary library = base::LoadNativeLibrary( 89 module_path.Append(L"osmesa.dll"), NULL); 90 if (!library) { 91 DVLOG(1) << "osmesa.dll not found"; 92 return false; 93 } 94 95 GLGetProcAddressProc get_proc_address = 96 reinterpret_cast<GLGetProcAddressProc>( 97 base::GetFunctionPointerFromNativeLibrary( 98 library, "OSMesaGetProcAddress")); 99 if (!get_proc_address) { 100 DLOG(ERROR) << "OSMesaGetProcAddress not found."; 101 base::UnloadNativeLibrary(library); 102 return false; 103 } 104 105 SetGLGetProcAddressProc(get_proc_address); 106 AddGLNativeLibrary(library); 107 SetGLImplementation(kGLImplementationOSMesaGL); 108 109 InitializeGLBindingsGL(); 110 InitializeGLBindingsOSMESA(); 111 break; 112 } 113 case kGLImplementationEGLGLES2: { 114 FilePath module_path; 115 if (!PathService::Get(base::DIR_MODULE, &module_path)) 116 return false; 117 118 // Attempt to load D3DX and its dependencies using the default search path 119 // and if that fails, using an absolute path. This is to ensure these DLLs 120 // are loaded before ANGLE is loaded in case they are not in the default 121 // search path. 122 LoadD3DXLibrary(module_path, base::StringPrintf(L"d3dcompiler_%d.dll", 123 kPinnedD3DXVersion)); 124 LoadD3DXLibrary(module_path, base::StringPrintf(L"d3dx9_%d.dll", 125 kPinnedD3DXVersion)); 126 127 FilePath gles_path; 128 const CommandLine* command_line = CommandLine::ForCurrentProcess(); 129 bool using_swift_shader = 130 command_line->GetSwitchValueASCII(switches::kUseGL) == "swiftshader"; 131 if (using_swift_shader) { 132 if (!command_line->HasSwitch(switches::kSwiftShaderPath)) 133 return false; 134 gles_path = 135 command_line->GetSwitchValuePath(switches::kSwiftShaderPath); 136 // Preload library 137 LoadLibrary(L"ddraw.dll"); 138 } else { 139 gles_path = module_path; 140 } 141 142 // Load libglesv2.dll before libegl.dll because the latter is dependent on 143 // the former and if there is another version of libglesv2.dll in the dll 144 // search path, it will get loaded instead. 145 base::NativeLibrary gles_library = base::LoadNativeLibrary( 146 gles_path.Append(L"libglesv2.dll"), NULL); 147 if (!gles_library) { 148 DVLOG(1) << "libglesv2.dll not found"; 149 return false; 150 } 151 152 // When using EGL, first try eglGetProcAddress and then Windows 153 // GetProcAddress on both the EGL and GLES2 DLLs. 154 base::NativeLibrary egl_library = base::LoadNativeLibrary( 155 gles_path.Append(L"libegl.dll"), NULL); 156 if (!egl_library) { 157 DVLOG(1) << "libegl.dll not found."; 158 base::UnloadNativeLibrary(gles_library); 159 return false; 160 } 161 162#if defined(ENABLE_SWIFTSHADER) 163 if (using_swift_shader) { 164 SetupSoftwareRenderer(gles_library); 165 } 166#endif 167 168 GLGetProcAddressProc get_proc_address = 169 reinterpret_cast<GLGetProcAddressProc>( 170 base::GetFunctionPointerFromNativeLibrary( 171 egl_library, "eglGetProcAddress")); 172 if (!get_proc_address) { 173 LOG(ERROR) << "eglGetProcAddress not found."; 174 base::UnloadNativeLibrary(egl_library); 175 base::UnloadNativeLibrary(gles_library); 176 return false; 177 } 178 179 SetGLGetProcAddressProc(get_proc_address); 180 AddGLNativeLibrary(egl_library); 181 AddGLNativeLibrary(gles_library); 182 SetGLImplementation(kGLImplementationEGLGLES2); 183 184 InitializeGLBindingsGL(); 185 InitializeGLBindingsEGL(); 186 187 // These two functions take single precision float rather than double 188 // precision float parameters in GLES. 189 ::gfx::g_driver_gl.fn.glClearDepthFn = MarshalClearDepthToClearDepthf; 190 ::gfx::g_driver_gl.fn.glDepthRangeFn = MarshalDepthRangeToDepthRangef; 191 break; 192 } 193 case kGLImplementationDesktopGL: { 194 // When using Windows OpenGL, first try wglGetProcAddress and then 195 // Windows GetProcAddress. 196 base::NativeLibrary library = base::LoadNativeLibrary( 197 FilePath(L"opengl32.dll"), NULL); 198 if (!library) { 199 DVLOG(1) << "opengl32.dll not found"; 200 return false; 201 } 202 203 GLGetProcAddressProc get_proc_address = 204 reinterpret_cast<GLGetProcAddressProc>( 205 base::GetFunctionPointerFromNativeLibrary( 206 library, "wglGetProcAddress")); 207 if (!get_proc_address) { 208 LOG(ERROR) << "wglGetProcAddress not found."; 209 base::UnloadNativeLibrary(library); 210 return false; 211 } 212 213 SetGLGetProcAddressProc(get_proc_address); 214 AddGLNativeLibrary(library); 215 SetGLImplementation(kGLImplementationDesktopGL); 216 217 InitializeGLBindingsGL(); 218 InitializeGLBindingsWGL(); 219 break; 220 } 221 case kGLImplementationMockGL: { 222 SetGLGetProcAddressProc(GetMockGLProcAddress); 223 SetGLImplementation(kGLImplementationMockGL); 224 InitializeGLBindingsGL(); 225 break; 226 } 227 default: 228 return false; 229 } 230 231 return true; 232} 233 234bool InitializeGLExtensionBindings(GLImplementation implementation, 235 GLContext* context) { 236 switch (implementation) { 237 case kGLImplementationOSMesaGL: 238 InitializeGLExtensionBindingsGL(context); 239 InitializeGLExtensionBindingsOSMESA(context); 240 break; 241 case kGLImplementationEGLGLES2: 242 InitializeGLExtensionBindingsGL(context); 243 InitializeGLExtensionBindingsEGL(context); 244 break; 245 case kGLImplementationDesktopGL: 246 InitializeGLExtensionBindingsGL(context); 247 InitializeGLExtensionBindingsWGL(context); 248 break; 249 case kGLImplementationMockGL: 250 InitializeGLExtensionBindingsGL(context); 251 break; 252 default: 253 return false; 254 } 255 256 return true; 257} 258 259void InitializeDebugGLBindings() { 260 InitializeDebugGLBindingsEGL(); 261 InitializeDebugGLBindingsGL(); 262 InitializeDebugGLBindingsOSMESA(); 263 InitializeDebugGLBindingsWGL(); 264} 265 266void ClearGLBindings() { 267 ClearGLBindingsEGL(); 268 ClearGLBindingsGL(); 269 ClearGLBindingsOSMESA(); 270 ClearGLBindingsWGL(); 271 SetGLImplementation(kGLImplementationNone); 272 UnloadGLNativeLibraries(); 273} 274 275} // namespace gfx 276