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) 590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "gpu/config/gpu_info_collector.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/debug/trace_event.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_number_conversions.h" 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_piece.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_bindings.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_context.h" 18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/gl/gl_implementation.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_surface.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<gfx::GLSurface> InitializeGLSurface() { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<gfx::GLSurface> surface( 257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size(1, 1))); 26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!surface.get()) { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "gfx::GLContext::CreateOffscreenGLSurface failed"; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return surface; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<gfx::GLContext> InitializeGLContext(gfx::GLSurface* surface) { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<gfx::GLContext> context( 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::GLContext::CreateGLContext(NULL, 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) surface, 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::PreferIntegratedGpu)); 40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!context.get()) { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "gfx::GLContext::CreateGLContext failed"; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!context->MakeCurrent(surface)) { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "gfx::GLContext::MakeCurrent() failed"; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return context; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetGLString(unsigned int pname) { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* gl_string = 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const char*>(glGetString(pname)); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (gl_string) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::string(gl_string); 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Return a version string in the format of "major.minor". 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetVersionFromString(const std::string& version_string) { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t begin = version_string.find_first_of("0123456789"); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (begin != std::string::npos) { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t end = version_string.find_first_not_of("01234567890.", begin); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string sub_string; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (end != std::string::npos) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sub_string = version_string.substr(begin, end - begin); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sub_string = version_string.substr(begin); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string> pieces; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SplitString(sub_string, '.', &pieces); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pieces.size() >= 2) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return pieces[0] + "." + pieces[1]; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace anonymous 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace gpu { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool CollectGraphicsInfoGL(GPUInfo* gpu_info) { 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TRACE_EVENT0("startup", "gpu_info_collector::CollectGraphicsInfoGL"); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!gfx::GLSurface::InitializeOneOff()) { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "gfx::GLSurface::InitializeOneOff() failed"; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<gfx::GLSurface> surface(InitializeGLSurface()); 91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!surface.get()) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<gfx::GLContext> context(InitializeGLContext(surface.get())); 95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!context.get()) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gpu_info->gl_renderer = GetGLString(GL_RENDERER); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gpu_info->gl_vendor = GetGLString(GL_VENDOR); 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gpu_info->gl_extensions = GetGLString(GL_EXTENSIONS); 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gpu_info->gl_version_string = GetGLString(GL_VERSION); 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string glsl_version_string = GetGLString(GL_SHADING_LANGUAGE_VERSION); 103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::GLWindowSystemBindingInfo window_system_binding_info; 105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (GetGLWindowSystemBindingInfo(&window_system_binding_info)) { 106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gpu_info->gl_ws_vendor = window_system_binding_info.vendor; 107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gpu_info->gl_ws_version = window_system_binding_info.version; 108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gpu_info->gl_ws_extensions = window_system_binding_info.extensions; 109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 111a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) bool supports_robustness = 112a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) gpu_info->gl_extensions.find("GL_EXT_robustness") != std::string::npos || 113a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) gpu_info->gl_extensions.find("GL_ARB_robustness") != std::string::npos; 114a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (supports_robustness) { 115a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) glGetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB, 116a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) reinterpret_cast<GLint*>(&gpu_info->gl_reset_notification_strategy)); 117a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 118a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(kbr): remove once the destruction of a current context automatically 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // clears the current context. 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context->ReleaseCurrent(surface.get()); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gpu_info->gl_version = GetVersionFromString(gpu_info->gl_version_string); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string glsl_version = GetVersionFromString(glsl_version_string); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gpu_info->pixel_shader_version = glsl_version; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gpu_info->vertex_shader_version = glsl_version; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return CollectDriverInfoGL(gpu_info); 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void MergeGPUInfoGL(GPUInfo* basic_gpu_info, 13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const GPUInfo& context_gpu_info) { 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(basic_gpu_info); 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) basic_gpu_info->gl_renderer = context_gpu_info.gl_renderer; 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) basic_gpu_info->gl_vendor = context_gpu_info.gl_vendor; 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) basic_gpu_info->gl_version_string = context_gpu_info.gl_version_string; 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) basic_gpu_info->gl_extensions = context_gpu_info.gl_extensions; 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) basic_gpu_info->gl_version = context_gpu_info.gl_version; 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) basic_gpu_info->pixel_shader_version = 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) context_gpu_info.pixel_shader_version; 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) basic_gpu_info->vertex_shader_version = 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) context_gpu_info.vertex_shader_version; 143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) basic_gpu_info->gl_ws_vendor = context_gpu_info.gl_ws_vendor; 144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) basic_gpu_info->gl_ws_version = context_gpu_info.gl_ws_version; 145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) basic_gpu_info->gl_ws_extensions = context_gpu_info.gl_ws_extensions; 146a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) basic_gpu_info->gl_reset_notification_strategy = 147a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) context_gpu_info.gl_reset_notification_strategy; 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!context_gpu_info.driver_vendor.empty()) 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) basic_gpu_info->driver_vendor = context_gpu_info.driver_vendor; 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!context_gpu_info.driver_version.empty()) 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) basic_gpu_info->driver_version = context_gpu_info.driver_version; 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) basic_gpu_info->can_lose_context = context_gpu_info.can_lose_context; 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) basic_gpu_info->sandboxed = context_gpu_info.sandboxed; 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) basic_gpu_info->finalized = context_gpu_info.finalized; 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) basic_gpu_info->initialization_time = context_gpu_info.initialization_time; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace gpu 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 162