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 "gpu/config/gpu_info_collector.h" 6 7 #include <string> 8 #include <vector> 9 10 #include "base/debug/trace_event.h" 11 #include "base/logging.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "base/strings/string_number_conversions.h" 14 #include "base/strings/string_piece.h" 15 #include "base/strings/string_split.h" 16 #include "ui/gl/gl_bindings.h" 17 #include "ui/gl/gl_context.h" 18 #include "ui/gl/gl_implementation.h" 19 #include "ui/gl/gl_surface.h" 20 21 namespace { 22 23 scoped_refptr<gfx::GLSurface> InitializeGLSurface() { 24 scoped_refptr<gfx::GLSurface> surface( 25 gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size())); 26 if (!surface.get()) { 27 LOG(ERROR) << "gfx::GLContext::CreateOffscreenGLSurface failed"; 28 return NULL; 29 } 30 31 return surface; 32 } 33 34 scoped_refptr<gfx::GLContext> InitializeGLContext(gfx::GLSurface* surface) { 35 36 scoped_refptr<gfx::GLContext> context( 37 gfx::GLContext::CreateGLContext(NULL, 38 surface, 39 gfx::PreferIntegratedGpu)); 40 if (!context.get()) { 41 LOG(ERROR) << "gfx::GLContext::CreateGLContext failed"; 42 return NULL; 43 } 44 45 if (!context->MakeCurrent(surface)) { 46 LOG(ERROR) << "gfx::GLContext::MakeCurrent() failed"; 47 return NULL; 48 } 49 50 return context; 51 } 52 53 std::string GetGLString(unsigned int pname) { 54 const char* gl_string = 55 reinterpret_cast<const char*>(glGetString(pname)); 56 if (gl_string) 57 return std::string(gl_string); 58 return std::string(); 59 } 60 61 // Return a version string in the format of "major.minor". 62 std::string GetVersionFromString(const std::string& version_string) { 63 size_t begin = version_string.find_first_of("0123456789"); 64 if (begin != std::string::npos) { 65 size_t end = version_string.find_first_not_of("01234567890.", begin); 66 std::string sub_string; 67 if (end != std::string::npos) 68 sub_string = version_string.substr(begin, end - begin); 69 else 70 sub_string = version_string.substr(begin); 71 std::vector<std::string> pieces; 72 base::SplitString(sub_string, '.', &pieces); 73 if (pieces.size() >= 2) 74 return pieces[0] + "." + pieces[1]; 75 } 76 return std::string(); 77 } 78 79 } // namespace anonymous 80 81 namespace gpu { 82 83 CollectInfoResult CollectGraphicsInfoGL(GPUInfo* gpu_info) { 84 TRACE_EVENT0("startup", "gpu_info_collector::CollectGraphicsInfoGL"); 85 DCHECK_NE(gfx::GetGLImplementation(), gfx::kGLImplementationNone); 86 87 scoped_refptr<gfx::GLSurface> surface(InitializeGLSurface()); 88 if (!surface.get()) { 89 LOG(ERROR) << "Could not create surface for info collection."; 90 return kCollectInfoFatalFailure; 91 } 92 93 scoped_refptr<gfx::GLContext> context(InitializeGLContext(surface.get())); 94 if (!context.get()) { 95 LOG(ERROR) << "Could not create context for info collection."; 96 return kCollectInfoFatalFailure; 97 } 98 99 gpu_info->gl_renderer = GetGLString(GL_RENDERER); 100 gpu_info->gl_vendor = GetGLString(GL_VENDOR); 101 gpu_info->gl_extensions = GetGLString(GL_EXTENSIONS); 102 gpu_info->gl_version = GetGLString(GL_VERSION); 103 std::string glsl_version_string = GetGLString(GL_SHADING_LANGUAGE_VERSION); 104 105 gfx::GLWindowSystemBindingInfo window_system_binding_info; 106 if (GetGLWindowSystemBindingInfo(&window_system_binding_info)) { 107 gpu_info->gl_ws_vendor = window_system_binding_info.vendor; 108 gpu_info->gl_ws_version = window_system_binding_info.version; 109 gpu_info->gl_ws_extensions = window_system_binding_info.extensions; 110 gpu_info->direct_rendering = window_system_binding_info.direct_rendering; 111 } 112 113 bool supports_robustness = 114 gpu_info->gl_extensions.find("GL_EXT_robustness") != std::string::npos || 115 gpu_info->gl_extensions.find("GL_ARB_robustness") != std::string::npos; 116 if (supports_robustness) { 117 glGetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB, 118 reinterpret_cast<GLint*>(&gpu_info->gl_reset_notification_strategy)); 119 } 120 121 // TODO(kbr): remove once the destruction of a current context automatically 122 // clears the current context. 123 context->ReleaseCurrent(surface.get()); 124 125 std::string glsl_version = GetVersionFromString(glsl_version_string); 126 gpu_info->pixel_shader_version = glsl_version; 127 gpu_info->vertex_shader_version = glsl_version; 128 129 return CollectDriverInfoGL(gpu_info); 130 } 131 132 void MergeGPUInfoGL(GPUInfo* basic_gpu_info, 133 const GPUInfo& context_gpu_info) { 134 DCHECK(basic_gpu_info); 135 basic_gpu_info->gl_renderer = context_gpu_info.gl_renderer; 136 basic_gpu_info->gl_vendor = context_gpu_info.gl_vendor; 137 basic_gpu_info->gl_version = context_gpu_info.gl_version; 138 basic_gpu_info->gl_extensions = context_gpu_info.gl_extensions; 139 basic_gpu_info->pixel_shader_version = 140 context_gpu_info.pixel_shader_version; 141 basic_gpu_info->vertex_shader_version = 142 context_gpu_info.vertex_shader_version; 143 basic_gpu_info->gl_ws_vendor = context_gpu_info.gl_ws_vendor; 144 basic_gpu_info->gl_ws_version = context_gpu_info.gl_ws_version; 145 basic_gpu_info->gl_ws_extensions = context_gpu_info.gl_ws_extensions; 146 basic_gpu_info->gl_reset_notification_strategy = 147 context_gpu_info.gl_reset_notification_strategy; 148 149 if (!context_gpu_info.driver_vendor.empty()) 150 basic_gpu_info->driver_vendor = context_gpu_info.driver_vendor; 151 if (!context_gpu_info.driver_version.empty()) 152 basic_gpu_info->driver_version = context_gpu_info.driver_version; 153 154 basic_gpu_info->can_lose_context = context_gpu_info.can_lose_context; 155 basic_gpu_info->sandboxed = context_gpu_info.sandboxed; 156 basic_gpu_info->direct_rendering = context_gpu_info.direct_rendering; 157 basic_gpu_info->finalized = context_gpu_info.finalized; 158 basic_gpu_info->initialization_time = context_gpu_info.initialization_time; 159 } 160 161 } // namespace gpu 162 163