// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/gpu/compositor_util.h"

#include <stddef.h>

#include <utility>

#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/field_trial.h"
#include "base/strings/string_number_conversions.h"
#include "base/sys_info.h"
#include "build/build_config.h"
#include "cc/base/math_util.h"
#include "cc/base/switches.h"
#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/public/browser/gpu_utils.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "gpu/config/gpu_feature_type.h"
#include "gpu/ipc/host/gpu_memory_buffer_support.h"
#include "media/media_features.h"
#include "ui/gl/gl_switches.h"

namespace content {

namespace {

static bool IsGpuRasterizationBlacklisted() {
  GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance();
  return manager->IsFeatureBlacklisted(
        gpu::GPU_FEATURE_TYPE_GPU_RASTERIZATION);
}

const char kGpuCompositingFeatureName[] = "gpu_compositing";
const char kWebGLFeatureName[] = "webgl";
const char kRasterizationFeatureName[] = "rasterization";
const char kMultipleRasterThreadsFeatureName[] = "multiple_raster_threads";
const char kNativeGpuMemoryBuffersFeatureName[] = "native_gpu_memory_buffers";
const char kWebGL2FeatureName[] = "webgl2";
const char kCheckerImagingFeatureName[] = "checker_imaging";

const int kMinRasterThreads = 1;
const int kMaxRasterThreads = 4;

const int kMinMSAASampleCount = 0;

struct GpuFeatureInfo {
  std::string name;
  bool blocked;
  bool disabled;
  std::string disabled_description;
  bool fallback_to_software;
};

const GpuFeatureInfo GetGpuFeatureInfo(size_t index, bool* eof) {
  const base::CommandLine& command_line =
      *base::CommandLine::ForCurrentProcess();
  GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance();
  gpu::GpuPreferences gpu_preferences = GetGpuPreferencesFromCommandLine();

  const GpuFeatureInfo kGpuFeatureInfo[] = {
    {"2d_canvas",
     manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS),
     command_line.HasSwitch(switches::kDisableAccelerated2dCanvas),
     "Accelerated 2D canvas is unavailable: either disabled via blacklist or"
     " the command line.",
     true},
    {kGpuCompositingFeatureName,
     manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING),
     command_line.HasSwitch(switches::kDisableGpuCompositing),
     "Gpu compositing has been disabled, either via blacklist, about:flags"
     " or the command line. The browser will fall back to software compositing"
     " and hardware acceleration will be unavailable.",
     true},
    {kWebGLFeatureName, !manager->IsWebGLEnabled(),
     command_line.HasSwitch(switches::kDisableExperimentalWebGL),
     "WebGL has been disabled via blacklist or the command line.", false},
    {"flash_3d", manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH3D),
     command_line.HasSwitch(switches::kDisableFlash3d),
     "Using 3d in flash has been disabled, either via blacklist, about:flags or"
     " the command line.",
     true},
    {"flash_stage3d",
     manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D),
     command_line.HasSwitch(switches::kDisableFlashStage3d),
     "Using Stage3d in Flash has been disabled, either via blacklist,"
     " about:flags or the command line.",
     true},
    {"flash_stage3d_baseline",
     manager->IsFeatureBlacklisted(
         gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE) ||
         manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D),
     command_line.HasSwitch(switches::kDisableFlashStage3d),
     "Using Stage3d Baseline profile in Flash has been disabled, either"
     " via blacklist, about:flags or the command line.",
     true},
    {"video_decode",
     manager->IsFeatureBlacklisted(
         gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE),
     command_line.HasSwitch(switches::kDisableAcceleratedVideoDecode),
     "Accelerated video decode has been disabled, either via blacklist,"
     " about:flags or the command line.",
     true},
#if BUILDFLAG(ENABLE_WEBRTC)
    {"video_encode",
     manager->IsFeatureBlacklisted(
         gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_ENCODE),
     command_line.HasSwitch(switches::kDisableWebRtcHWEncoding),
     "Accelerated video encode has been disabled, either via blacklist,"
     " about:flags or the command line.",
     true},
#endif
#if defined(OS_CHROMEOS)
    {"panel_fitting",
     manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_PANEL_FITTING),
     command_line.HasSwitch(switches::kDisablePanelFitting),
     "Panel fitting has been disabled, either via blacklist, about:flags or"
     " the command line.",
     false},
#endif
    {kRasterizationFeatureName,
     IsGpuRasterizationBlacklisted() && !IsGpuRasterizationEnabled() &&
         !IsForceGpuRasterizationEnabled(),
     !IsGpuRasterizationEnabled() && !IsForceGpuRasterizationEnabled() &&
         !IsGpuRasterizationBlacklisted(),
     "Accelerated rasterization has been disabled, either via blacklist,"
     " about:flags or the command line.",
     true},
    {kMultipleRasterThreadsFeatureName, false,
     NumberOfRendererRasterThreads() == 1, "Raster is using a single thread.",
     false},
    {kNativeGpuMemoryBuffersFeatureName, false,
     !gpu::AreNativeGpuMemoryBuffersEnabled(),
     "Native GpuMemoryBuffers have been disabled, either via about:flags"
     " or command line.",
     true},
    {kWebGL2FeatureName,
     manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL2),
     command_line.HasSwitch(switches::kDisableES3APIs),
     "WebGL2 has been disabled via blacklist or the command line.", false},
    {kCheckerImagingFeatureName, false, !IsCheckerImagingEnabled(),
     "Checker-imaging has been disabled via finch trial or the command line.",
     false},
  };
  DCHECK(index < arraysize(kGpuFeatureInfo));
  *eof = (index == arraysize(kGpuFeatureInfo) - 1);
  return kGpuFeatureInfo[index];
}

}  // namespace

int NumberOfRendererRasterThreads() {
  int num_processors = base::SysInfo::NumberOfProcessors();

#if defined(OS_ANDROID) || \
    (defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY))
  // Android and ChromeOS ARM devices may report 6 to 8 CPUs for big.LITTLE
  // configurations. Limit the number of raster threads based on maximum of
  // 4 big cores.
  num_processors = std::min(num_processors, 4);
#endif

  int num_raster_threads = num_processors / 2;

#if defined(OS_ANDROID)
  // Limit the number of raster threads to 1 on Android.
  // TODO(reveman): Remove this when we have a better mechanims to prevent
  // pre-paint raster work from slowing down non-raster work. crbug.com/504515
  num_raster_threads = 1;
#endif

  const base::CommandLine& command_line =
      *base::CommandLine::ForCurrentProcess();

  if (command_line.HasSwitch(switches::kNumRasterThreads)) {
    std::string string_value = command_line.GetSwitchValueASCII(
        switches::kNumRasterThreads);
    if (!base::StringToInt(string_value, &num_raster_threads)) {
      DLOG(WARNING) << "Failed to parse switch " <<
          switches::kNumRasterThreads  << ": " << string_value;
    }
  }

  return cc::MathUtil::ClampToRange(num_raster_threads, kMinRasterThreads,
                                    kMaxRasterThreads);
}

bool IsZeroCopyUploadEnabled() {
  const base::CommandLine& command_line =
      *base::CommandLine::ForCurrentProcess();
#if defined(OS_MACOSX)
  return !command_line.HasSwitch(switches::kDisableZeroCopy);
#else
  return command_line.HasSwitch(switches::kEnableZeroCopy);
#endif
}

bool IsPartialRasterEnabled() {
  const auto& command_line = *base::CommandLine::ForCurrentProcess();
  return !command_line.HasSwitch(switches::kDisablePartialRaster);
}

bool IsGpuMemoryBufferCompositorResourcesEnabled() {
  const base::CommandLine& command_line =
      *base::CommandLine::ForCurrentProcess();
  if (command_line.HasSwitch(
          switches::kEnableGpuMemoryBufferCompositorResources)) {
    return true;
  }
  if (command_line.HasSwitch(
          switches::kDisableGpuMemoryBufferCompositorResources)) {
    return false;
  }

  // Native GPU memory buffers are required.
  if (!gpu::AreNativeGpuMemoryBuffersEnabled())
    return false;

#if defined(OS_MACOSX)
  return true;
#else
  return false;
#endif
}

bool IsGpuRasterizationEnabled() {
  GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance();
  return manager->IsFeatureEnabled(gpu::GPU_FEATURE_TYPE_GPU_RASTERIZATION);
}

bool IsForceGpuRasterizationEnabled() {
  const base::CommandLine& command_line =
      *base::CommandLine::ForCurrentProcess();
  return command_line.HasSwitch(switches::kForceGpuRasterization);
}

int GpuRasterizationMSAASampleCount() {
  const base::CommandLine& command_line =
      *base::CommandLine::ForCurrentProcess();

  if (!command_line.HasSwitch(switches::kGpuRasterizationMSAASampleCount))
#if defined(OS_ANDROID)
    return 4;
#else
    // Desktop platforms will compute this automatically based on DPI.
    return -1;
#endif
  std::string string_value = command_line.GetSwitchValueASCII(
      switches::kGpuRasterizationMSAASampleCount);
  int msaa_sample_count = 0;
  if (base::StringToInt(string_value, &msaa_sample_count) &&
      msaa_sample_count >= kMinMSAASampleCount) {
    return msaa_sample_count;
  } else {
    DLOG(WARNING) << "Failed to parse switch "
                  << switches::kGpuRasterizationMSAASampleCount << ": "
                  << string_value;
    return 0;
  }
}

bool IsMainFrameBeforeActivationEnabled() {
  if (base::SysInfo::NumberOfProcessors() < 4)
    return false;

  const base::CommandLine& command_line =
      *base::CommandLine::ForCurrentProcess();

  if (command_line.HasSwitch(cc::switches::kDisableMainFrameBeforeActivation))
    return false;

  if (command_line.HasSwitch(cc::switches::kEnableMainFrameBeforeActivation))
    return true;

  return true;
}

bool IsCheckerImagingEnabled() {
  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
          cc::switches::kEnableCheckerImaging))
    return true;

  if (base::FeatureList::IsEnabled(features::kCheckerImaging))
    return true;

  return false;
}

std::unique_ptr<base::DictionaryValue> GetFeatureStatus() {
  GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance();
  std::string gpu_access_blocked_reason;
  bool gpu_access_blocked =
      !manager->GpuAccessAllowed(&gpu_access_blocked_reason);

  auto feature_status_dict = base::MakeUnique<base::DictionaryValue>();

  bool eof = false;
  for (size_t i = 0; !eof; ++i) {
    const GpuFeatureInfo gpu_feature_info = GetGpuFeatureInfo(i, &eof);
    std::string status;
    if (gpu_feature_info.disabled) {
      status = "disabled";
      if (gpu_feature_info.fallback_to_software)
        status += "_software";
      else
        status += "_off";
    } else if (gpu_feature_info.blocked ||
               gpu_access_blocked) {
      status = "unavailable";
      if (gpu_feature_info.fallback_to_software)
        status += "_software";
      else
        status += "_off";
    } else {
      status = "enabled";
      if (gpu_feature_info.name == kWebGLFeatureName &&
          manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING))
        status += "_readback";
      if (gpu_feature_info.name == kRasterizationFeatureName) {
        if (IsForceGpuRasterizationEnabled())
          status += "_force";
      }
      if (gpu_feature_info.name == kMultipleRasterThreadsFeatureName) {
        const base::CommandLine& command_line =
            *base::CommandLine::ForCurrentProcess();
        if (command_line.HasSwitch(switches::kNumRasterThreads))
          status += "_force";
      }
      if (gpu_feature_info.name == kMultipleRasterThreadsFeatureName)
        status += "_on";
      if (gpu_feature_info.name == kCheckerImagingFeatureName) {
        const base::CommandLine& command_line =
            *base::CommandLine::ForCurrentProcess();
        if (command_line.HasSwitch(cc::switches::kEnableCheckerImaging))
          status += "_force";
        status += "_on";
      }
    }
    if (gpu_feature_info.name == kWebGLFeatureName &&
        (gpu_feature_info.blocked || gpu_access_blocked) &&
        manager->ShouldUseSwiftShader()) {
      status = "unavailable_software";
    }

    feature_status_dict->SetString(gpu_feature_info.name, status);
  }
  return feature_status_dict;
}

std::unique_ptr<base::ListValue> GetProblems() {
  GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance();
  std::string gpu_access_blocked_reason;
  bool gpu_access_blocked =
      !manager->GpuAccessAllowed(&gpu_access_blocked_reason);

  auto problem_list = base::MakeUnique<base::ListValue>();
  manager->GetBlacklistReasons(problem_list.get());

  if (gpu_access_blocked) {
    auto problem = base::MakeUnique<base::DictionaryValue>();
    problem->SetString("description",
        "GPU process was unable to boot: " + gpu_access_blocked_reason);
    problem->Set("crBugs", base::MakeUnique<base::ListValue>());
    auto disabled_features = base::MakeUnique<base::ListValue>();
    disabled_features->AppendString("all");
    problem->Set("affectedGpuSettings", std::move(disabled_features));
    problem->SetString("tag", "disabledFeatures");
    problem_list->Insert(0, std::move(problem));
  }

  bool eof = false;
  for (size_t i = 0; !eof; ++i) {
    const GpuFeatureInfo gpu_feature_info = GetGpuFeatureInfo(i, &eof);
    if (gpu_feature_info.disabled) {
      auto problem = base::MakeUnique<base::DictionaryValue>();
      problem->SetString(
          "description", gpu_feature_info.disabled_description);
      problem->Set("crBugs", base::MakeUnique<base::ListValue>());
      auto disabled_features = base::MakeUnique<base::ListValue>();
      disabled_features->AppendString(gpu_feature_info.name);
      problem->Set("affectedGpuSettings", std::move(disabled_features));
      problem->SetString("tag", "disabledFeatures");
      problem_list->Append(std::move(problem));
    }
  }
  return problem_list;
}

std::vector<std::string> GetDriverBugWorkarounds() {
  return GpuDataManagerImpl::GetInstance()->GetDriverBugWorkarounds();
}

}  // namespace content
