190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file.
490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "gpu/config/gpu_info_collector.h"
690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/android/build_info.h"
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/command_line.h"
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/logging.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/strings/string_piece.h"
1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/strings/string_split.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ui/gl/gl_bindings.h"
154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ui/gl/gl_context.h"
164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ui/gl/gl_surface.h"
1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace {
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)std::string GetDriverVersionFromString(const std::string& version_string) {
2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Extract driver version from the second number in a string like:
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // "OpenGL ES 2.0 V@6.0 AU@ (CL@2946718)"
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Exclude first "2.0".
2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  size_t begin = version_string.find_first_of("0123456789");
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (begin == std::string::npos)
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return "0";
2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  size_t end = version_string.find_first_not_of("01234567890.", begin);
2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Extract number of the form "%d.%d"
3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  begin = version_string.find_first_of("0123456789", end);
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (begin == std::string::npos)
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return "0";
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  end = version_string.find_first_not_of("01234567890.", begin);
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string sub_string;
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (end != std::string::npos)
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    sub_string = version_string.substr(begin, end - begin);
3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  else
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    sub_string = version_string.substr(begin);
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::vector<std::string> pieces;
4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::SplitString(sub_string, '.', &pieces);
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (pieces.size() < 2)
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return "0";
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return pieces[0] + "." + pieces[1];
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)class ScopedRestoreNonOwnedEGLContext {
484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public:
494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ScopedRestoreNonOwnedEGLContext();
504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ~ScopedRestoreNonOwnedEGLContext();
514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private:
534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EGLContext context_;
544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EGLDisplay display_;
554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EGLSurface draw_surface_;
564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EGLSurface read_surface_;
574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)ScopedRestoreNonOwnedEGLContext::ScopedRestoreNonOwnedEGLContext()
604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  : context_(EGL_NO_CONTEXT),
614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    display_(EGL_NO_DISPLAY),
624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    draw_surface_(EGL_NO_SURFACE),
634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    read_surface_(EGL_NO_SURFACE) {
644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // This should only used to restore a context that is not created or owned by
654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Chromium native code, but created by Android system itself.
664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(!gfx::GLContext::GetCurrent());
674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  context_ = eglGetCurrentContext();
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  display_ = eglGetCurrentDisplay();
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  draw_surface_ = eglGetCurrentSurface(EGL_DRAW);
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  read_surface_ = eglGetCurrentSurface(EGL_READ);
724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)ScopedRestoreNonOwnedEGLContext::~ScopedRestoreNonOwnedEGLContext() {
754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (context_ == EGL_NO_CONTEXT || display_ == EGL_NO_DISPLAY ||
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      draw_surface_ == EGL_NO_SURFACE || read_surface_ == EGL_NO_SURFACE)
774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!eglMakeCurrent(display_, draw_surface_, read_surface_, context_))
804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    LOG(WARNING) << "Failed to restore EGL context";
814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace gpu {
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
87effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochCollectInfoResult CollectContextGraphicsInfo(GPUInfo* gpu_info) {
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return CollectBasicGraphicsInfo(gpu_info);
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciCollectInfoResult CollectGpuID(uint32* vendor_id, uint32* device_id) {
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(vendor_id && device_id);
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  *vendor_id = 0;
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  *device_id = 0;
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return kCollectInfoNonFatalFailure;
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
98effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochCollectInfoResult CollectBasicGraphicsInfo(GPUInfo* gpu_info) {
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  gpu_info->can_lose_context = false;
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  gpu_info->machine_model_name =
1020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      base::android::BuildInfo::GetInstance()->model();
10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Create a short-lived context on the UI thread to collect the GL strings.
1054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Make sure we restore the existing context if there is one.
1064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ScopedRestoreNonOwnedEGLContext restore_context;
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CollectInfoResult result = CollectGraphicsInfoGL(gpu_info);
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gpu_info->basic_info_state = result;
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gpu_info->context_info_state = result;
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return result;
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
113effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochCollectInfoResult CollectDriverInfoGL(GPUInfo* gpu_info) {
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  gpu_info->driver_version = GetDriverVersionFromString(
115010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      gpu_info->gl_version);
1164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  gpu_info->gpu.vendor_string = gpu_info->gl_vendor;
1174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  gpu_info->gpu.device_string = gpu_info->gl_renderer;
118effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return kCollectInfoSuccess;
11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void MergeGPUInfo(GPUInfo* basic_gpu_info,
12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                  const GPUInfo& context_gpu_info) {
12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  MergeGPUInfoGL(basic_gpu_info, context_gpu_info);
12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace gpu
127