<commit_before>// 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/gpu_data_manager_impl.h"

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/stringprintf.h"
#include "base/sys_info.h"
#include "base/values.h"
#include "base/version.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/gpu/gpu_info_collector.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/gpu_data_manager_observer.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "ui/base/ui_base_switches.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_switches.h"
#include "webkit/plugins/plugin_switches.h"

using content::BrowserThread;
using content::GpuDataManagerObserver;
using content::GpuFeatureType;

// static
content::GpuDataManager* content::GpuDataManager::GetInstance() {
  return GpuDataManagerImpl::GetInstance();
}

// static
GpuDataManagerImpl* GpuDataManagerImpl::GetInstance() {
  return Singleton<GpuDataManagerImpl>::get();
}

GpuDataManagerImpl::GpuDataManagerImpl()
    : complete_gpu_info_already_requested_(false),
      complete_gpu_info_available_(false),
      gpu_feature_type_(content::GPU_FEATURE_TYPE_UNKNOWN),
      preliminary_gpu_feature_type_(content::GPU_FEATURE_TYPE_UNKNOWN),
      observer_list_(new GpuDataManagerObserverList),
      software_rendering_(false),
      card_blacklisted_(false) {
  Initialize();
}

void GpuDataManagerImpl::Initialize() {
  CommandLine* command_line = CommandLine::ForCurrentProcess();
  if (command_line->HasSwitch(switches::kDisableAcceleratedCompositing)) {
    command_line->AppendSwitch(switches::kDisableAccelerated2dCanvas);
    command_line->AppendSwitch(switches::kDisableAcceleratedLayers);
  }

  if (!command_line->HasSwitch(switches::kSkipGpuDataLoading)) {
    content::GPUInfo gpu_info;
    gpu_info_collector::CollectPreliminaryGraphicsInfo(&gpu_info);
    {
      base::AutoLock auto_lock(gpu_info_lock_);
      gpu_info_ = gpu_info;
    }
  }
  if (command_line->HasSwitch(switches::kDisableGpu))
    BlacklistCard();
}

GpuDataManagerImpl::~GpuDataManagerImpl() {
}

void GpuDataManagerImpl::RequestCompleteGpuInfoIfNeeded() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  if (complete_gpu_info_already_requested_ || complete_gpu_info_available_)
    return;
  complete_gpu_info_already_requested_ = true;

  GpuProcessHost::SendOnIO(
      GpuProcessHost::GPU_PROCESS_KIND_UNSANDBOXED,
      content::CAUSE_FOR_GPU_LAUNCH_GPUDATAMANAGER_REQUESTCOMPLETEGPUINFOIFNEEDED,
      new GpuMsg_CollectGraphicsInfo());
}

bool GpuDataManagerImpl::IsCompleteGPUInfoAvailable() const {
  return complete_gpu_info_available_;
}

void GpuDataManagerImpl::UpdateGpuInfo(const content::GPUInfo& gpu_info) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  {
    base::AutoLock auto_lock(gpu_info_lock_);
#if defined(ARCH_CPU_X86_FAMILY)
    if (!gpu_info.gpu.vendor_id || !gpu_info.gpu.device_id)
      gpu_info_.finalized = true;
    else
#endif
      gpu_info_ = gpu_info;
    complete_gpu_info_available_ =
        complete_gpu_info_available_ || gpu_info_.finalized;
    complete_gpu_info_already_requested_ =
        complete_gpu_info_already_requested_ || gpu_info_.finalized;
    content::GetContentClient()->SetGpuInfo(gpu_info_);
  }

  // We have to update GpuFeatureType before notify all the observers.
  NotifyGpuInfoUpdate();
}

content::GPUInfo GpuDataManagerImpl::GetGPUInfo() const {
  return gpu_info_;
}

void GpuDataManagerImpl::AddLogMessage(Value* msg) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  log_messages_.Append(msg);
}

GpuFeatureType GpuDataManagerImpl::GetGpuFeatureType() {
  if (software_rendering_) {
    GpuFeatureType flags;

    // Skia's software rendering is probably more efficient than going through
    // software emulation of the GPU, so use that.
    flags = content::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS;
    return flags;
  }

  return gpu_feature_type_;
}

bool GpuDataManagerImpl::GpuAccessAllowed() {
  if (software_rendering_)
    return true;

  if (!gpu_info_.gpu_accessible)
    return false;

  if (card_blacklisted_)
    return false;

  // We only need to block GPU process if more features are disallowed other
  // than those in the preliminary gpu feature flags because the latter work
  // through renderer commandline switches.
  uint32 mask = ~(preliminary_gpu_feature_type_);
  return (gpu_feature_type_ & mask) == 0;
}

void GpuDataManagerImpl::AddObserver(GpuDataManagerObserver* observer) {
  observer_list_->AddObserver(observer);
}

void GpuDataManagerImpl::RemoveObserver(GpuDataManagerObserver* observer) {
  observer_list_->RemoveObserver(observer);
}

void GpuDataManagerImpl::AppendRendererCommandLine(
    CommandLine* command_line) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DCHECK(command_line);

  uint32 flags = GetGpuFeatureType();
  if ((flags & content::GPU_FEATURE_TYPE_WEBGL)) {
    if (!command_line->HasSwitch(switches::kDisableExperimentalWebGL))
      command_line->AppendSwitch(switches::kDisableExperimentalWebGL);
    if (!command_line->HasSwitch(switches::kDisablePepper3dForUntrustedUse))
      command_line->AppendSwitch(switches::kDisablePepper3dForUntrustedUse);
  }
  if ((flags & content::GPU_FEATURE_TYPE_MULTISAMPLING) &&
      !command_line->HasSwitch(switches::kDisableGLMultisampling))
    command_line->AppendSwitch(switches::kDisableGLMultisampling);
  if ((flags & content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) &&
      !command_line->HasSwitch(switches::kDisableAcceleratedCompositing))
    command_line->AppendSwitch(switches::kDisableAcceleratedCompositing);
  if ((flags & content::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS) &&
      !command_line->HasSwitch(switches::kDisableAccelerated2dCanvas))
    command_line->AppendSwitch(switches::kDisableAccelerated2dCanvas);
}

void GpuDataManagerImpl::AppendGpuCommandLine(
    CommandLine* command_line) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  DCHECK(command_line);

  std::string use_gl =
      CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switches::kUseGL);
  FilePath swiftshader_path =
      CommandLine::ForCurrentProcess()->GetSwitchValuePath(
          switches::kSwiftShaderPath);
  uint32 flags = GetGpuFeatureType();
  if ((flags & content::GPU_FEATURE_TYPE_MULTISAMPLING) &&
      !command_line->HasSwitch(switches::kDisableGLMultisampling))
    command_line->AppendSwitch(switches::kDisableGLMultisampling);

  if (software_rendering_) {
    command_line->AppendSwitchASCII(switches::kUseGL, "swiftshader");
    if (swiftshader_path.empty())
      swiftshader_path = swiftshader_path_;
  } else if ((flags & (content::GPU_FEATURE_TYPE_WEBGL |
                content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING |
                content::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)) &&
      (use_gl == "any")) {
    command_line->AppendSwitchASCII(
        switches::kUseGL, gfx::kGLImplementationOSMesaName);
  } else if (!use_gl.empty()) {
    command_line->AppendSwitchASCII(switches::kUseGL, use_gl);
  }

  if (!swiftshader_path.empty())
    command_line->AppendSwitchPath(switches::kSwiftShaderPath,
                                   swiftshader_path);

  {
    base::AutoLock auto_lock(gpu_info_lock_);
    if (gpu_info_.optimus)
      command_line->AppendSwitch(switches::kReduceGpuSandbox);
    if (gpu_info_.amd_switchable) {
      // The image transport surface currently doesn't work with AMD Dynamic
      // Switchable graphics.
      command_line->AppendSwitch(switches::kReduceGpuSandbox);
      command_line->AppendSwitch(switches::kDisableImageTransportSurface);
    }
    // Pass GPU and driver information to GPU process. We try to avoid full GPU
    // info collection at GPU process startup, but we need gpu vendor_id,
    // device_id, driver_vendor, driver_version for deciding whether we need to
    // collect full info (on Linux) and for crash reporting purpose.
    command_line->AppendSwitchASCII(switches::kGpuVendorID,
        base::StringPrintf("0x%04x", gpu_info_.gpu.vendor_id));
    command_line->AppendSwitchASCII(switches::kGpuDeviceID,
        base::StringPrintf("0x%04x", gpu_info_.gpu.device_id));
    command_line->AppendSwitchASCII(switches::kGpuDriverVendor,
        gpu_info_.driver_vendor);
    command_line->AppendSwitchASCII(switches::kGpuDriverVersion,
        gpu_info_.driver_version);
  }
}

void GpuDataManagerImpl::AppendPluginCommandLine(
    CommandLine* command_line) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  DCHECK(command_line);

#if defined(OS_MACOSX)
  uint32 flags = GetGpuFeatureType();
  // TODO(jbauman): Add proper blacklist support for core animation plugins so
  // special-casing this video card won't be necessary. See
  // http://crbug.com/134015
  if ((flags & content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) ||
      (gpu_info_.gpu.vendor_id == 0x8086 &&
       gpu_info_.gpu.device_id == 0x0166) ||
      CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kDisableAcceleratedCompositing)) {
    if (!command_line->HasSwitch(
           switches::kDisableCoreAnimationPlugins))
      command_line->AppendSwitch(
          switches::kDisableCoreAnimationPlugins);
  }
#endif
}

void GpuDataManagerImpl::SetGpuFeatureType(GpuFeatureType feature_type) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  UpdateGpuFeatureType(feature_type);
  preliminary_gpu_feature_type_ = gpu_feature_type_;
}

void GpuDataManagerImpl::NotifyGpuInfoUpdate() {
  observer_list_->Notify(&GpuDataManagerObserver::OnGpuInfoUpdate);
}

void GpuDataManagerImpl::UpdateGpuFeatureType(
    GpuFeatureType embedder_feature_type) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  CommandLine* command_line = CommandLine::ForCurrentProcess();
  int flags = embedder_feature_type;

  // Force disable using the GPU for these features, even if they would
  // otherwise be allowed.
  if (card_blacklisted_ ||
      command_line->HasSwitch(switches::kBlacklistAcceleratedCompositing)) {
    flags |= content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING;
  }
  if (card_blacklisted_ ||
      command_line->HasSwitch(switches::kBlacklistWebGL)) {
    flags |= content::GPU_FEATURE_TYPE_WEBGL;
  }
  gpu_feature_type_ = static_cast<GpuFeatureType>(flags);

  EnableSoftwareRenderingIfNecessary();
}

void GpuDataManagerImpl::RegisterSwiftShaderPath(const FilePath& path) {
  swiftshader_path_ = path;
  EnableSoftwareRenderingIfNecessary();
}

const base::ListValue& GpuDataManagerImpl::GetLogMessages() const {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  return log_messages_;
}

void GpuDataManagerImpl::EnableSoftwareRenderingIfNecessary() {
  if (!GpuAccessAllowed() ||
      (gpu_feature_type_ & content::GPU_FEATURE_TYPE_WEBGL)) {
#if defined(ENABLE_SWIFTSHADER)
    if (!swiftshader_path_.empty() &&
        !CommandLine::ForCurrentProcess()->HasSwitch(
             switches::kDisableSoftwareRasterizer))
      software_rendering_ = true;
#endif
  }
}

bool GpuDataManagerImpl::ShouldUseSoftwareRendering() {
  return software_rendering_;
}

void GpuDataManagerImpl::BlacklistCard() {
  card_blacklisted_ = true;

  gpu_feature_type_ = content::GPU_FEATURE_TYPE_ALL;

  EnableSoftwareRenderingIfNecessary();
  NotifyGpuInfoUpdate();
}

<commit_msg>Also blacklist Core Animation on Macbook Pros.<commit_after>// 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/gpu_data_manager_impl.h"

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/stringprintf.h"
#include "base/sys_info.h"
#include "base/values.h"
#include "base/version.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/gpu/gpu_info_collector.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/gpu_data_manager_observer.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "ui/base/ui_base_switches.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_switches.h"
#include "webkit/plugins/plugin_switches.h"

using content::BrowserThread;
using content::GpuDataManagerObserver;
using content::GpuFeatureType;

// static
content::GpuDataManager* content::GpuDataManager::GetInstance() {
  return GpuDataManagerImpl::GetInstance();
}

// static
GpuDataManagerImpl* GpuDataManagerImpl::GetInstance() {
  return Singleton<GpuDataManagerImpl>::get();
}

GpuDataManagerImpl::GpuDataManagerImpl()
    : complete_gpu_info_already_requested_(false),
      complete_gpu_info_available_(false),
      gpu_feature_type_(content::GPU_FEATURE_TYPE_UNKNOWN),
      preliminary_gpu_feature_type_(content::GPU_FEATURE_TYPE_UNKNOWN),
      observer_list_(new GpuDataManagerObserverList),
      software_rendering_(false),
      card_blacklisted_(false) {
  Initialize();
}

void GpuDataManagerImpl::Initialize() {
  CommandLine* command_line = CommandLine::ForCurrentProcess();
  if (command_line->HasSwitch(switches::kDisableAcceleratedCompositing)) {
    command_line->AppendSwitch(switches::kDisableAccelerated2dCanvas);
    command_line->AppendSwitch(switches::kDisableAcceleratedLayers);
  }

  if (!command_line->HasSwitch(switches::kSkipGpuDataLoading)) {
    content::GPUInfo gpu_info;
    gpu_info_collector::CollectPreliminaryGraphicsInfo(&gpu_info);
    {
      base::AutoLock auto_lock(gpu_info_lock_);
      gpu_info_ = gpu_info;
    }
  }
  if (command_line->HasSwitch(switches::kDisableGpu))
    BlacklistCard();
}

GpuDataManagerImpl::~GpuDataManagerImpl() {
}

void GpuDataManagerImpl::RequestCompleteGpuInfoIfNeeded() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  if (complete_gpu_info_already_requested_ || complete_gpu_info_available_)
    return;
  complete_gpu_info_already_requested_ = true;

  GpuProcessHost::SendOnIO(
      GpuProcessHost::GPU_PROCESS_KIND_UNSANDBOXED,
      content::CAUSE_FOR_GPU_LAUNCH_GPUDATAMANAGER_REQUESTCOMPLETEGPUINFOIFNEEDED,
      new GpuMsg_CollectGraphicsInfo());
}

bool GpuDataManagerImpl::IsCompleteGPUInfoAvailable() const {
  return complete_gpu_info_available_;
}

void GpuDataManagerImpl::UpdateGpuInfo(const content::GPUInfo& gpu_info) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  {
    base::AutoLock auto_lock(gpu_info_lock_);
#if defined(ARCH_CPU_X86_FAMILY)
    if (!gpu_info.gpu.vendor_id || !gpu_info.gpu.device_id)
      gpu_info_.finalized = true;
    else
#endif
      gpu_info_ = gpu_info;
    complete_gpu_info_available_ =
        complete_gpu_info_available_ || gpu_info_.finalized;
    complete_gpu_info_already_requested_ =
        complete_gpu_info_already_requested_ || gpu_info_.finalized;
    content::GetContentClient()->SetGpuInfo(gpu_info_);
  }

  // We have to update GpuFeatureType before notify all the observers.
  NotifyGpuInfoUpdate();
}

content::GPUInfo GpuDataManagerImpl::GetGPUInfo() const {
  return gpu_info_;
}

void GpuDataManagerImpl::AddLogMessage(Value* msg) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  log_messages_.Append(msg);
}

GpuFeatureType GpuDataManagerImpl::GetGpuFeatureType() {
  if (software_rendering_) {
    GpuFeatureType flags;

    // Skia's software rendering is probably more efficient than going through
    // software emulation of the GPU, so use that.
    flags = content::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS;
    return flags;
  }

  return gpu_feature_type_;
}

bool GpuDataManagerImpl::GpuAccessAllowed() {
  if (software_rendering_)
    return true;

  if (!gpu_info_.gpu_accessible)
    return false;

  if (card_blacklisted_)
    return false;

  // We only need to block GPU process if more features are disallowed other
  // than those in the preliminary gpu feature flags because the latter work
  // through renderer commandline switches.
  uint32 mask = ~(preliminary_gpu_feature_type_);
  return (gpu_feature_type_ & mask) == 0;
}

void GpuDataManagerImpl::AddObserver(GpuDataManagerObserver* observer) {
  observer_list_->AddObserver(observer);
}

void GpuDataManagerImpl::RemoveObserver(GpuDataManagerObserver* observer) {
  observer_list_->RemoveObserver(observer);
}

void GpuDataManagerImpl::AppendRendererCommandLine(
    CommandLine* command_line) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DCHECK(command_line);

  uint32 flags = GetGpuFeatureType();
  if ((flags & content::GPU_FEATURE_TYPE_WEBGL)) {
    if (!command_line->HasSwitch(switches::kDisableExperimentalWebGL))
      command_line->AppendSwitch(switches::kDisableExperimentalWebGL);
    if (!command_line->HasSwitch(switches::kDisablePepper3dForUntrustedUse))
      command_line->AppendSwitch(switches::kDisablePepper3dForUntrustedUse);
  }
  if ((flags & content::GPU_FEATURE_TYPE_MULTISAMPLING) &&
      !command_line->HasSwitch(switches::kDisableGLMultisampling))
    command_line->AppendSwitch(switches::kDisableGLMultisampling);
  if ((flags & content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) &&
      !command_line->HasSwitch(switches::kDisableAcceleratedCompositing))
    command_line->AppendSwitch(switches::kDisableAcceleratedCompositing);
  if ((flags & content::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS) &&
      !command_line->HasSwitch(switches::kDisableAccelerated2dCanvas))
    command_line->AppendSwitch(switches::kDisableAccelerated2dCanvas);
}

void GpuDataManagerImpl::AppendGpuCommandLine(
    CommandLine* command_line) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  DCHECK(command_line);

  std::string use_gl =
      CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switches::kUseGL);
  FilePath swiftshader_path =
      CommandLine::ForCurrentProcess()->GetSwitchValuePath(
          switches::kSwiftShaderPath);
  uint32 flags = GetGpuFeatureType();
  if ((flags & content::GPU_FEATURE_TYPE_MULTISAMPLING) &&
      !command_line->HasSwitch(switches::kDisableGLMultisampling))
    command_line->AppendSwitch(switches::kDisableGLMultisampling);

  if (software_rendering_) {
    command_line->AppendSwitchASCII(switches::kUseGL, "swiftshader");
    if (swiftshader_path.empty())
      swiftshader_path = swiftshader_path_;
  } else if ((flags & (content::GPU_FEATURE_TYPE_WEBGL |
                content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING |
                content::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)) &&
      (use_gl == "any")) {
    command_line->AppendSwitchASCII(
        switches::kUseGL, gfx::kGLImplementationOSMesaName);
  } else if (!use_gl.empty()) {
    command_line->AppendSwitchASCII(switches::kUseGL, use_gl);
  }

  if (!swiftshader_path.empty())
    command_line->AppendSwitchPath(switches::kSwiftShaderPath,
                                   swiftshader_path);

  {
    base::AutoLock auto_lock(gpu_info_lock_);
    if (gpu_info_.optimus)
      command_line->AppendSwitch(switches::kReduceGpuSandbox);
    if (gpu_info_.amd_switchable) {
      // The image transport surface currently doesn't work with AMD Dynamic
      // Switchable graphics.
      command_line->AppendSwitch(switches::kReduceGpuSandbox);
      command_line->AppendSwitch(switches::kDisableImageTransportSurface);
    }
    // Pass GPU and driver information to GPU process. We try to avoid full GPU
    // info collection at GPU process startup, but we need gpu vendor_id,
    // device_id, driver_vendor, driver_version for deciding whether we need to
    // collect full info (on Linux) and for crash reporting purpose.
    command_line->AppendSwitchASCII(switches::kGpuVendorID,
        base::StringPrintf("0x%04x", gpu_info_.gpu.vendor_id));
    command_line->AppendSwitchASCII(switches::kGpuDeviceID,
        base::StringPrintf("0x%04x", gpu_info_.gpu.device_id));
    command_line->AppendSwitchASCII(switches::kGpuDriverVendor,
        gpu_info_.driver_vendor);
    command_line->AppendSwitchASCII(switches::kGpuDriverVersion,
        gpu_info_.driver_version);
  }
}

void GpuDataManagerImpl::AppendPluginCommandLine(
    CommandLine* command_line) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  DCHECK(command_line);

#if defined(OS_MACOSX)
  uint32 flags = GetGpuFeatureType();
  // TODO(jbauman): Add proper blacklist support for core animation plugins so
  // special-casing this video card won't be necessary. See
  // http://crbug.com/134015
  if ((flags & content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) ||
      (gpu_info_.gpu.vendor_id == 0x8086 &&  // Intel
       gpu_info_.gpu.device_id == 0x0166) ||  // HD 4000
      (gpu_info_.gpu.vendor_id == 0x10de &&  // NVidia
       gpu_info_.gpu.device_id == 0x0fd5) ||  // GeForce GT 650M
      CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kDisableAcceleratedCompositing)) {
    if (!command_line->HasSwitch(
           switches::kDisableCoreAnimationPlugins))
      command_line->AppendSwitch(
          switches::kDisableCoreAnimationPlugins);
  }
#endif
}

void GpuDataManagerImpl::SetGpuFeatureType(GpuFeatureType feature_type) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  UpdateGpuFeatureType(feature_type);
  preliminary_gpu_feature_type_ = gpu_feature_type_;
}

void GpuDataManagerImpl::NotifyGpuInfoUpdate() {
  observer_list_->Notify(&GpuDataManagerObserver::OnGpuInfoUpdate);
}

void GpuDataManagerImpl::UpdateGpuFeatureType(
    GpuFeatureType embedder_feature_type) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  CommandLine* command_line = CommandLine::ForCurrentProcess();
  int flags = embedder_feature_type;

  // Force disable using the GPU for these features, even if they would
  // otherwise be allowed.
  if (card_blacklisted_ ||
      command_line->HasSwitch(switches::kBlacklistAcceleratedCompositing)) {
    flags |= content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING;
  }
  if (card_blacklisted_ ||
      command_line->HasSwitch(switches::kBlacklistWebGL)) {
    flags |= content::GPU_FEATURE_TYPE_WEBGL;
  }
  gpu_feature_type_ = static_cast<GpuFeatureType>(flags);

  EnableSoftwareRenderingIfNecessary();
}

void GpuDataManagerImpl::RegisterSwiftShaderPath(const FilePath& path) {
  swiftshader_path_ = path;
  EnableSoftwareRenderingIfNecessary();
}

const base::ListValue& GpuDataManagerImpl::GetLogMessages() const {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  return log_messages_;
}

void GpuDataManagerImpl::EnableSoftwareRenderingIfNecessary() {
  if (!GpuAccessAllowed() ||
      (gpu_feature_type_ & content::GPU_FEATURE_TYPE_WEBGL)) {
#if defined(ENABLE_SWIFTSHADER)
    if (!swiftshader_path_.empty() &&
        !CommandLine::ForCurrentProcess()->HasSwitch(
             switches::kDisableSoftwareRasterizer))
      software_rendering_ = true;
#endif
  }
}

bool GpuDataManagerImpl::ShouldUseSoftwareRendering() {
  return software_rendering_;
}

void GpuDataManagerImpl::BlacklistCard() {
  card_blacklisted_ = true;

  gpu_feature_type_ = content::GPU_FEATURE_TYPE_ALL;

  EnableSoftwareRenderingIfNecessary();
  NotifyGpuInfoUpdate();
}

<|endoftext|>


<commit_before>/** \copyright
 * Copyright (c) 2019, Mike Dunston
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are  permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \file Can.hxx
 *
 * ESP32 adapter code using the WiFiClient provided by the WiFiServer code
 * for interfacing with the OpenMRN stack.
 *
 * @author Mike Dunston
 * @date 13 January 2019
 */

// This include is exclusive against freertos_drivers/arduino/Esp32WiFiClientAdapter.hxx
#ifndef _FREERTOS_DRIVERS_ARDUINO_ESP32WIFI_HXX_
#define _FREERTOS_DRIVERS_ARDUINO_ESP32WIFI_HXX_

#include <Arduino.h>
#include <WiFi.h>

class Esp32WiFiClientAdapter {
public:
    WiFiClientAdapter(WiFiClient client) : client_(client){
        client_.setNoDelay(true);
    }
    // on the ESP32 there is no TX limit method
    size_t availableForWrite() {
        return client_.connected();
    }
    size_t write(const char *buffer, size_t len) {
        if(client_.connected()) {
            return client_.write(buffer, len);
        }
        return 0;
    }
    size_t available() {
        if(client_.connected()) {
            return client_.available();
        }
        return 0;
    }
    size_t read(const char *buffer, size_t len) {
        size_t bytesRead = 0;
        if(client_.connected()) {
            bytesRead = client_.read((uint8_t *)buffer, len);
        }
        return bytesRead;
    }
private:
    WiFiClient client_;
};

#endif /* _FREERTOS_DRIVERS_ARDUINO_ESP32WIFI_HXX_ */<commit_msg>fix constructor name<commit_after>/** \copyright
 * Copyright (c) 2019, Mike Dunston
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are  permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \file Can.hxx
 *
 * ESP32 adapter code using the WiFiClient provided by the WiFiServer code
 * for interfacing with the OpenMRN stack.
 *
 * @author Mike Dunston
 * @date 13 January 2019
 */

// This include is exclusive against freertos_drivers/arduino/Esp32WiFiClientAdapter.hxx
#ifndef _FREERTOS_DRIVERS_ARDUINO_ESP32WIFI_HXX_
#define _FREERTOS_DRIVERS_ARDUINO_ESP32WIFI_HXX_

#include <Arduino.h>
#include <WiFi.h>

class Esp32WiFiClientAdapter {
public:
    Esp32WiFiClientAdapter(WiFiClient client) : client_(client){
        client_.setNoDelay(true);
    }
    // on the ESP32 there is no TX limit method
    size_t availableForWrite() {
        return client_.connected();
    }
    size_t write(const char *buffer, size_t len) {
        if(client_.connected()) {
            return client_.write(buffer, len);
        }
        return 0;
    }
    size_t available() {
        if(client_.connected()) {
            return client_.available();
        }
        return 0;
    }
    size_t read(const char *buffer, size_t len) {
        size_t bytesRead = 0;
        if(client_.connected()) {
            bytesRead = client_.read((uint8_t *)buffer, len);
        }
        return bytesRead;
    }
private:
    WiFiClient client_;
};

#endif /* _FREERTOS_DRIVERS_ARDUINO_ESP32WIFI_HXX_ */<|endoftext|>


<commit_before>// 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.

// Tests for CppBoundClass, in conjunction with CppBindingExample.  Binds
// a CppBindingExample class into JavaScript in a custom test shell and tests
// the binding from the outside by loading JS into the shell.

#include "base/strings/utf_string_conversions.h"
#include "content/public/renderer/render_view_observer.h"
#include "content/public/test/render_view_test.h"
#include "third_party/WebKit/public/platform/WebURLRequest.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebElement.h"
#include "webkit/renderer/cpp_binding_example.h"

using webkit_glue::CppArgumentList;
using webkit_glue::CppBindingExample;
using webkit_glue::CppVariant;

namespace content {

class CppBindingExampleSubObject : public CppBindingExample {
 public:
  CppBindingExampleSubObject() {
    sub_value_.Set("sub!");
    BindProperty("sub_value", &sub_value_);
  }
 private:
  CppVariant sub_value_;
};

class CppBindingExampleWithOptionalFallback : public CppBindingExample {
 public:
  CppBindingExampleWithOptionalFallback() {
    BindProperty("sub_object", sub_object_.GetAsCppVariant());
  }

  void set_fallback_method_enabled(bool state) {
    BindFallbackCallback(state ?
        base::Bind(&CppBindingExampleWithOptionalFallback::fallbackMethod,
                   base::Unretained(this))
        : CppBoundClass::Callback());
  }

  // The fallback method does nothing, but because of it the JavaScript keeps
  // running when a nonexistent method is called on an object.
  void fallbackMethod(const CppArgumentList& args, CppVariant* result) {
  }

 private:
  CppBindingExampleSubObject sub_object_;
};

class TestObserver : public RenderViewObserver {
 public:
  explicit TestObserver(RenderView* render_view)
      : RenderViewObserver(render_view) {}
  virtual void DidClearWindowObject(WebKit::WebFrame* frame) OVERRIDE {
    example_bound_class_.BindToJavascript(frame, "example");
  }
  void set_fallback_method_enabled(bool use_fallback) {
    example_bound_class_.set_fallback_method_enabled(use_fallback);
  }
 private:
  CppBindingExampleWithOptionalFallback example_bound_class_;
};

class CppBoundClassTest : public RenderViewTest {
 public:
  CppBoundClassTest() {}

  virtual void SetUp() OVERRIDE {
    RenderViewTest::SetUp();
    observer_.reset(new TestObserver(view_));
    observer_->set_fallback_method_enabled(useFallback());

    WebKit::WebURLRequest url_request;
    url_request.initialize();
    url_request.setURL(GURL("about:blank"));

    GetMainFrame()->loadRequest(url_request);
    ProcessPendingMessages();
  }

  // Executes the specified JavaScript and checks that the resulting document
  // text is empty.
  void CheckJavaScriptFailure(const std::string& javascript) {
    ExecuteJavaScript(javascript.c_str());
    EXPECT_EQ(
        "",
        UTF16ToASCII(GetMainFrame()->document().documentElement().innerText()));
  }

  void CheckTrue(const std::string& expression) {
    int was_page_a = -1;
    string16 check_page_a =
        ASCIIToUTF16(std::string("Number(") + expression + ")");
    EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_a, &was_page_a));
    EXPECT_EQ(1, was_page_a);
  }

 protected:
  virtual bool useFallback() {
    return false;
  }

 private:
  scoped_ptr<TestObserver> observer_;
};

class CppBoundClassWithFallbackMethodTest : public CppBoundClassTest {
 protected:
  virtual bool useFallback() OVERRIDE {
    return true;
  }
};

// Ensures that the example object has been bound to JS.
TEST_F(CppBoundClassTest, ObjectExists) {
  CheckTrue("typeof window.example == 'object'");

  // An additional check to test our test.
  CheckTrue("typeof window.invalid_object == 'undefined'");
}

TEST_F(CppBoundClassTest, PropertiesAreInitialized) {
  CheckTrue("example.my_value == 10");

  CheckTrue("example.my_other_value == 'Reinitialized!'");
}

TEST_F(CppBoundClassTest, SubOject) {
  CheckTrue("typeof window.example.sub_object == 'object'");

  CheckTrue("example.sub_object.sub_value == 'sub!'");
}

TEST_F(CppBoundClassTest, SetAndGetProperties) {
  // The property on the left will be set to the value on the right, then
  // checked to make sure it holds that same value.
  static const std::string tests[] = {
    "example.my_value", "7",
    "example.my_value", "'test'",
    "example.my_other_value", "3.14",
    "example.my_other_value", "false",
    "" // Array end marker: insert additional test pairs before this.
  };

  for (int i = 0; tests[i] != ""; i += 2) {
    std::string left = tests[i];
    std::string right = tests[i + 1];
    // left = right;
    std::string js = left;
    js.append(" = ");
    js.append(right);
    js.append(";");
    ExecuteJavaScript(js.c_str());
    std::string expression = left;
    expression += " == ";
    expression += right;
    CheckTrue(expression);
  }
}

TEST_F(CppBoundClassTest, SetAndGetPropertiesWithCallbacks) {
  // TODO(dglazkov): fix NPObject issues around failing property setters and
  // getters and add tests for situations when GetProperty or SetProperty fail.
  ExecuteJavaScript("example.my_value_with_callback = 10;");
  CheckTrue("example.my_value_with_callback == 10");

  ExecuteJavaScript("example.my_value_with_callback = 11;");
  CheckTrue("example.my_value_with_callback == 11");

  CheckTrue("example.same == 42");

  ExecuteJavaScript("example.same = 24;");
  CheckTrue("example.same == 42");
}

TEST_F(CppBoundClassTest, InvokeMethods) {
  // The expression on the left is expected to return the value on the right.
  static const std::string tests[] = {
    "example.echoValue(true) == true",
    "example.echoValue(13) == 13",
    "example.echoValue(2.718) == 2.718",
    "example.echoValue('yes') == 'yes'",
    "example.echoValue() == null",     // Too few arguments

    "example.echoType(false) == true",
    "example.echoType(19) == 3.14159",
    "example.echoType(9.876) == 3.14159",
    "example.echoType('test string') == 'Success!'",
    "example.echoType() == null",      // Too few arguments

    // Comparing floats that aren't integer-valued is usually problematic due
    // to rounding, but exact powers of 2 should also be safe.
    "example.plus(2.5, 18.0) == 20.5",
    "example.plus(2, 3.25) == 5.25",
    "example.plus(2, 3) == 5",
    "example.plus() == null",             // Too few arguments
    "example.plus(1) == null",            // Too few arguments
    "example.plus(1, 'test') == null",    // Wrong argument type
    "example.plus('test', 2) == null",    // Wrong argument type
    "example.plus('one', 'two') == null", // Wrong argument type
    "" // Array end marker: insert additional test pairs before this.
  };

  for (int i = 0; tests[i] != ""; i++)
    CheckTrue(tests[i]);

  ExecuteJavaScript("example.my_value = 3.25; example.my_other_value = 1.25;");
  CheckTrue("example.plus(example.my_value, example.my_other_value) == 4.5");
}

// Tests that invoking a nonexistent method with no fallback method stops the
// script's execution
TEST_F(CppBoundClassTest,
       InvokeNonexistentMethodNoFallback) {
  std::string js = "example.nonExistentMethod();document.writeln('SUCCESS');";
  CheckJavaScriptFailure(js);
}

// Ensures existent methods can be invoked successfully when the fallback method
// is used
TEST_F(CppBoundClassWithFallbackMethodTest,
       InvokeExistentMethodsWithFallback) {
  CheckTrue("example.echoValue(34) == 34");
}

}  // namespace content
<commit_msg>Delete CppBound class after the test ends.<commit_after>// 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.

// Tests for CppBoundClass, in conjunction with CppBindingExample.  Binds
// a CppBindingExample class into JavaScript in a custom test shell and tests
// the binding from the outside by loading JS into the shell.

#include "base/strings/utf_string_conversions.h"
#include "content/public/renderer/render_view_observer.h"
#include "content/public/test/render_view_test.h"
#include "third_party/WebKit/public/platform/WebURLRequest.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebElement.h"
#include "webkit/renderer/cpp_binding_example.h"

using webkit_glue::CppArgumentList;
using webkit_glue::CppBindingExample;
using webkit_glue::CppVariant;

namespace content {

class CppBindingExampleSubObject : public CppBindingExample {
 public:
  CppBindingExampleSubObject() {
    sub_value_.Set("sub!");
    BindProperty("sub_value", &sub_value_);
  }
 private:
  CppVariant sub_value_;
};

class CppBindingExampleWithOptionalFallback : public CppBindingExample {
 public:
  CppBindingExampleWithOptionalFallback() {
    BindProperty("sub_object", sub_object_.GetAsCppVariant());
  }

  void set_fallback_method_enabled(bool state) {
    BindFallbackCallback(state ?
        base::Bind(&CppBindingExampleWithOptionalFallback::fallbackMethod,
                   base::Unretained(this))
        : CppBoundClass::Callback());
  }

  // The fallback method does nothing, but because of it the JavaScript keeps
  // running when a nonexistent method is called on an object.
  void fallbackMethod(const CppArgumentList& args, CppVariant* result) {
  }

 private:
  CppBindingExampleSubObject sub_object_;
};

class TestObserver : public RenderViewObserver {
 public:
  explicit TestObserver(RenderView* render_view)
      : RenderViewObserver(render_view) {}
  virtual void DidClearWindowObject(WebKit::WebFrame* frame) OVERRIDE {
    example_bound_class_.BindToJavascript(frame, "example");
  }
  void set_fallback_method_enabled(bool use_fallback) {
    example_bound_class_.set_fallback_method_enabled(use_fallback);
  }
 private:
  CppBindingExampleWithOptionalFallback example_bound_class_;
};

class CppBoundClassTest : public RenderViewTest {
 public:
  CppBoundClassTest() {}

  virtual void SetUp() OVERRIDE {
    RenderViewTest::SetUp();
    observer_.reset(new TestObserver(view_));
    observer_->set_fallback_method_enabled(useFallback());

    WebKit::WebURLRequest url_request;
    url_request.initialize();
    url_request.setURL(GURL("about:blank"));

    GetMainFrame()->loadRequest(url_request);
    ProcessPendingMessages();
  }

  virtual void TearDown() OVERRIDE {
    observer_.reset();
    RenderViewTest::TearDown();
  }

  // Executes the specified JavaScript and checks that the resulting document
  // text is empty.
  void CheckJavaScriptFailure(const std::string& javascript) {
    ExecuteJavaScript(javascript.c_str());
    EXPECT_EQ(
        "",
        UTF16ToASCII(GetMainFrame()->document().documentElement().innerText()));
  }

  void CheckTrue(const std::string& expression) {
    int was_page_a = -1;
    string16 check_page_a =
        ASCIIToUTF16(std::string("Number(") + expression + ")");
    EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_a, &was_page_a));
    EXPECT_EQ(1, was_page_a);
  }

 protected:
  virtual bool useFallback() {
    return false;
  }

 private:
  scoped_ptr<TestObserver> observer_;
};

class CppBoundClassWithFallbackMethodTest : public CppBoundClassTest {
 protected:
  virtual bool useFallback() OVERRIDE {
    return true;
  }
};

// Ensures that the example object has been bound to JS.
TEST_F(CppBoundClassTest, ObjectExists) {
  CheckTrue("typeof window.example == 'object'");

  // An additional check to test our test.
  CheckTrue("typeof window.invalid_object == 'undefined'");
}

TEST_F(CppBoundClassTest, PropertiesAreInitialized) {
  CheckTrue("example.my_value == 10");

  CheckTrue("example.my_other_value == 'Reinitialized!'");
}

TEST_F(CppBoundClassTest, SubOject) {
  CheckTrue("typeof window.example.sub_object == 'object'");

  CheckTrue("example.sub_object.sub_value == 'sub!'");
}

TEST_F(CppBoundClassTest, SetAndGetProperties) {
  // The property on the left will be set to the value on the right, then
  // checked to make sure it holds that same value.
  static const std::string tests[] = {
    "example.my_value", "7",
    "example.my_value", "'test'",
    "example.my_other_value", "3.14",
    "example.my_other_value", "false",
    "" // Array end marker: insert additional test pairs before this.
  };

  for (int i = 0; tests[i] != ""; i += 2) {
    std::string left = tests[i];
    std::string right = tests[i + 1];
    // left = right;
    std::string js = left;
    js.append(" = ");
    js.append(right);
    js.append(";");
    ExecuteJavaScript(js.c_str());
    std::string expression = left;
    expression += " == ";
    expression += right;
    CheckTrue(expression);
  }
}

TEST_F(CppBoundClassTest, SetAndGetPropertiesWithCallbacks) {
  // TODO(dglazkov): fix NPObject issues around failing property setters and
  // getters and add tests for situations when GetProperty or SetProperty fail.
  ExecuteJavaScript("example.my_value_with_callback = 10;");
  CheckTrue("example.my_value_with_callback == 10");

  ExecuteJavaScript("example.my_value_with_callback = 11;");
  CheckTrue("example.my_value_with_callback == 11");

  CheckTrue("example.same == 42");

  ExecuteJavaScript("example.same = 24;");
  CheckTrue("example.same == 42");
}

TEST_F(CppBoundClassTest, InvokeMethods) {
  // The expression on the left is expected to return the value on the right.
  static const std::string tests[] = {
    "example.echoValue(true) == true",
    "example.echoValue(13) == 13",
    "example.echoValue(2.718) == 2.718",
    "example.echoValue('yes') == 'yes'",
    "example.echoValue() == null",     // Too few arguments

    "example.echoType(false) == true",
    "example.echoType(19) == 3.14159",
    "example.echoType(9.876) == 3.14159",
    "example.echoType('test string') == 'Success!'",
    "example.echoType() == null",      // Too few arguments

    // Comparing floats that aren't integer-valued is usually problematic due
    // to rounding, but exact powers of 2 should also be safe.
    "example.plus(2.5, 18.0) == 20.5",
    "example.plus(2, 3.25) == 5.25",
    "example.plus(2, 3) == 5",
    "example.plus() == null",             // Too few arguments
    "example.plus(1) == null",            // Too few arguments
    "example.plus(1, 'test') == null",    // Wrong argument type
    "example.plus('test', 2) == null",    // Wrong argument type
    "example.plus('one', 'two') == null", // Wrong argument type
    "" // Array end marker: insert additional test pairs before this.
  };

  for (int i = 0; tests[i] != ""; i++)
    CheckTrue(tests[i]);

  ExecuteJavaScript("example.my_value = 3.25; example.my_other_value = 1.25;");
  CheckTrue("example.plus(example.my_value, example.my_other_value) == 4.5");
}

// Tests that invoking a nonexistent method with no fallback method stops the
// script's execution
TEST_F(CppBoundClassTest,
       InvokeNonexistentMethodNoFallback) {
  std::string js = "example.nonExistentMethod();document.writeln('SUCCESS');";
  CheckJavaScriptFailure(js);
}

// Ensures existent methods can be invoked successfully when the fallback method
// is used
TEST_F(CppBoundClassWithFallbackMethodTest,
       InvokeExistentMethodsWithFallback) {
  CheckTrue("example.echoValue(34) == 34");
}

}  // namespace content
<|endoftext|>


<commit_before>/**
 * \file
 * \brief ThisThread namespace implementation
 *
 * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2015-02-16
 */

#include "distortos/ThisThread.hpp"

#include "distortos/scheduler/getScheduler.hpp"
#include "distortos/scheduler/Scheduler.hpp"

namespace distortos
{

namespace ThisThread
{

/*---------------------------------------------------------------------------------------------------------------------+
| global functions
+---------------------------------------------------------------------------------------------------------------------*/

ThreadBase& get()
{
	return scheduler::getScheduler().getCurrentThreadBase();
}

uint8_t getEffectivePriority()
{
	return scheduler::getScheduler().getCurrentThreadControlBlock().getEffectivePriority();
}

uint8_t getPriority()
{
	return scheduler::getScheduler().getCurrentThreadControlBlock().getPriority();
}

void setPriority(const uint8_t priority, const bool alwaysBehind)
{
	scheduler::getScheduler().getCurrentThreadControlBlock().setPriority(priority, alwaysBehind);
}

void sleepFor(const TickClock::duration duration)
{
	sleepUntil(TickClock::now() + duration + TickClock::duration{1});
}

void sleepUntil(const TickClock::time_point timePoint)
{
	scheduler::ThreadControlBlockList sleepingList {scheduler::getScheduler().getThreadControlBlockListAllocator(),
			scheduler::ThreadControlBlock::State::Sleeping};
	scheduler::getScheduler().blockUntil(sleepingList, timePoint);
}

void yield()
{
	scheduler::getScheduler().yield();
}

}	// namespace ThisThread

}	// namespace distortos
<commit_msg>ThisThread::sleepUntil(): small optimization<commit_after>/**
 * \file
 * \brief ThisThread namespace implementation
 *
 * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2015-02-16
 */

#include "distortos/ThisThread.hpp"

#include "distortos/scheduler/getScheduler.hpp"
#include "distortos/scheduler/Scheduler.hpp"

namespace distortos
{

namespace ThisThread
{

/*---------------------------------------------------------------------------------------------------------------------+
| global functions
+---------------------------------------------------------------------------------------------------------------------*/

ThreadBase& get()
{
	return scheduler::getScheduler().getCurrentThreadBase();
}

uint8_t getEffectivePriority()
{
	return scheduler::getScheduler().getCurrentThreadControlBlock().getEffectivePriority();
}

uint8_t getPriority()
{
	return scheduler::getScheduler().getCurrentThreadControlBlock().getPriority();
}

void setPriority(const uint8_t priority, const bool alwaysBehind)
{
	scheduler::getScheduler().getCurrentThreadControlBlock().setPriority(priority, alwaysBehind);
}

void sleepFor(const TickClock::duration duration)
{
	sleepUntil(TickClock::now() + duration + TickClock::duration{1});
}

void sleepUntil(const TickClock::time_point timePoint)
{
	auto& scheduler = scheduler::getScheduler();
	scheduler::ThreadControlBlockList sleepingList {scheduler.getThreadControlBlockListAllocator(),
			scheduler::ThreadControlBlock::State::Sleeping};
	scheduler.blockUntil(sleepingList, timePoint);
}

void yield()
{
	scheduler::getScheduler().yield();
}

}	// namespace ThisThread

}	// namespace distortos
<|endoftext|>


<commit_before>#include "gum/Statistics.h"
#include "gum/StatFPS.h"
#include "gum/StatTag.h"
#include "gum/GUM_GTxt.h"

#include <logger.h>
#include <glp_loop.h>
#include <ps_3d.h>
#include <sprite2/pre_defined.h>
#include S2_MAT_HEADER
#include <sprite2/StatDrawCall.h>
#include <sprite2/StatPingPong.h>
#include <sprite2/StatTopNodes.h>
#include <sprite2/StatSymbol.h>
#include <shaderlab/ShaderMgr.h>
#include <shaderlab/Statistics.h>
#include <shaderlab/StatDrawCall.h>

#include <string>

#include <time.h>

namespace gum
{

SINGLETON_DEFINITION(Statistics);

static const float FPS_SMOOTHING = 0.99f;

Statistics::Statistics()
	: m_flags(0)
	, m_tpf(0)
	, m_tpf_smooth(0)
	, m_no_stat_begin(0)
	, m_no_stat_tot(0)
	, m_opt_enable(false)
{
	memset(&m_mem, 0, sizeof(m_mem));
}

void Statistics::EnableGraph(bool enable)
{
	if (enable) {
		m_flags |= FLAG_PRINT_GRAPH;
	} else {
		m_flags &= ~FLAG_PRINT_GRAPH;
	}
}

void Statistics::EnableConsole(bool enable)
{
	if (enable) {
		m_flags |= FLAG_PRINT_CONSOLE;
	} else {
		m_flags &= ~FLAG_PRINT_CONSOLE;
	}
}

void Statistics::EnableFile(bool enable)
{
	if (enable == IsFileEnable()) {
		return;
	}

	if (enable)
	{
		m_flags |= FLAG_PRINT_FILE;

#ifdef __ANDROID__
		m_fout.open("/sdcard/lr_stat.bin", std::ofstream::out | std::ofstream::binary);
#else
		m_fout.open("lr_stat.bin", std::ofstream::out | std::ofstream::binary);
#endif // __ANDROID__
	}
	else
	{
		m_flags &= ~FLAG_PRINT_FILE;

		m_fout.close();
	}
}

bool Statistics::IsGraphEnable() const
{
	return (m_flags & FLAG_PRINT_GRAPH) != 0;
}

bool Statistics::IsConsoleEnable() const
{
	return (m_flags & FLAG_PRINT_CONSOLE) != 0;
}

bool Statistics::IsFileEnable() const
{
	return (m_flags & FLAG_PRINT_FILE) != 0;
}

void Statistics::Update()
{
	if (m_flags == 0) {
		return;
	}

	m_tpf = glp_get_dt();
	m_tpf_smooth = (m_tpf_smooth * FPS_SMOOTHING) + m_tpf * (1.0f - FPS_SMOOTHING);
}

void Statistics::Print()
{
	StatTag::Instance()->PrintScreen();

	if (m_flags == 0) {
		return;
	}

	if (m_flags & FLAG_PRINT_GRAPH) {
		PrintScreen();
	}
	if (m_flags & FLAG_PRINT_CONSOLE) {
		PrintConsole();
	}
	if (m_flags & FLAG_PRINT_FILE) {
		PrintFile();
	}
}

void Statistics::Reset()
{
	if (m_flags == 0) {
		return;
	}

	m_tpf = 0;

	sl::Statistics::Instance()->Reset();
	sl::StatDrawCall::Instance()->Reset();

	s2::StatDrawCall::Instance()->Reset();
	s2::StatPingPong::Instance()->Reset();
	s2::StatTopNodes::Instance()->Reset();
	s2::StatSymbol::Instance()->Reset();
}

void Statistics::Flush()
{
	StatTag::Instance()->Flush();
}

void Statistics::NoStatBegin()
{
	m_no_stat_begin = glp_get_time();
}

void Statistics::NoStatEnd()
{
	m_no_stat_tot = (glp_get_time() - m_no_stat_begin);
}

void Statistics::OptEnable(bool enable)
{
	m_opt_enable = enable;
}

void Statistics::SetMem(float tot, float lua)
{
	m_mem.tot = tot;
	m_mem.lua = lua;
}

void Statistics::PrintScreen() const
{
	sl::ShaderMgr* mgr = sl::ShaderMgr::Instance();
	mgr->SetShader(sl::SPRITE2);

	static char buf[512];

	const int w = 960;
	const int top = 280;

	S2_MAT mt;
	mt.Translate(0, top);

	sprintf(buf, "OPT: %s, emitter: %d", m_opt_enable ? "open" : "closed", p3d_emitter_count());
	GTxt::Instance()->Draw(mt, buf, w);

	mt.Translate(0, -30);
	sprintf(buf, "FPS: %.1f, ms: %.1f, ex:%.1f", 1000.0f / m_tpf, m_tpf_smooth, m_no_stat_tot / 1000.0f);
	GTxt::Instance()->Draw(mt, buf, w);

	mt.Translate(0, -30);
	sprintf(buf, "MEM: tot %.1f, tex %.1f, lua %.1f", m_mem.tot, m_mem.tex, m_mem.lua);
	GTxt::Instance()->Draw(mt, buf, w);

	static std::string buf_str;
	buf_str.reserve(512);

	mt.Translate(0, -30);
	sl::Statistics::Instance()->Print(buf_str);
	GTxt::Instance()->Draw(mt, buf_str, w);
	buf_str.clear();

	mt.Translate(0, -30);
	s2::StatDrawCall::Instance()->Print(buf_str);
	GTxt::Instance()->Draw(mt, buf_str, w);
	buf_str.clear();

	mt.Translate(0, -40);
	s2::StatPingPong::Instance()->Print(buf_str);
	GTxt::Instance()->Draw(mt, buf_str, w);
	buf_str.clear();

	mt.Translate(450, -100);
	s2::StatTopNodes::Instance()->Print(buf_str);
	GTxt::Instance()->Draw(mt, buf_str, w);
	buf_str.clear();

// 	mt.Translate(450, 180);
// 	s2::StatSymbol::Instance()->Print(buf_str);
// 	GTxt::Instance()->Draw(mt, buf_str, w);
// 	buf_str.clear();

// 	mt.Translate(0, -230);
// 	sl::StatDrawCall::Instance()->Print(buf_str);
// 	GTxt::Instance()->Draw(mt, buf_str, w);
// 	buf_str.clear();

	mgr->FlushShader();
}

void Statistics::PrintConsole() const
{
	static const int PRINT_COUNT = 30;
	static int count = 0;
	++count;
	if (count == PRINT_COUNT)
	{
		count = 0;
		sl::Statistics* stat = sl::Statistics::Instance();
		int dc = stat->GetDrawCall();
		int count = stat->GetVertices();
		float fps_curr = StatFPS::Instance()->GetFPSCurr();
		float curr_cost = 0;
		if (fps_curr != 0) {
			curr_cost = 1000.0f / fps_curr;
		}
		LOGI("fps %.1f, cost %.1f, dc %d, vertices %d, cost avg %.1f\n",
			1000.0f / m_tpf_smooth, m_tpf_smooth, dc, count, curr_cost);
	}
}

void Statistics::PrintFile() const
{
	sl::Statistics* sl_stat = sl::Statistics::Instance();

	static char buf[512];
	sprintf(buf, "timestamp %lu, cost %.1f, vertices %d, dc %d\n",
		time(NULL), m_tpf_smooth, sl_stat->GetVertices(), sl_stat->GetDrawCall());
	m_fout << buf;

// 	static std::string buf_str;
// 	buf_str.reserve(1024);
// 	s2::StatTopNodes::Instance()->Print(buf_str);
// 	m_fout << buf_str;

	static const int FLUSH_COUNT = 100;
	static int count = 0;
	++count;
	if (count == FLUSH_COUNT) {
		count = 0;
		m_fout.flush();
	}
}

}<commit_msg>[ADDED] obj count to stat<commit_after>#include "gum/Statistics.h"
#include "gum/StatFPS.h"
#include "gum/StatTag.h"
#include "gum/GUM_GTxt.h"
#include "gum/SymbolPool.h"
#include "gum/Image.h"

#include <logger.h>
#include <glp_loop.h>
#include <ps_3d.h>
#include <sprite2/pre_defined.h>
#include S2_MAT_HEADER
#include <sprite2/StatDrawCall.h>
#include <sprite2/StatPingPong.h>
#include <sprite2/StatTopNodes.h>
#include <sprite2/StatSymbol.h>
#include <sprite2/S2_Sprite.h>
#include <sprite2/S2_Actor.h>
#include <shaderlab/ShaderMgr.h>
#include <shaderlab/Statistics.h>
#include <shaderlab/StatDrawCall.h>

#include <string>

#include <time.h>

namespace gum
{

SINGLETON_DEFINITION(Statistics);

static const float FPS_SMOOTHING = 0.99f;

Statistics::Statistics()
	: m_flags(0)
	, m_tpf(0)
	, m_tpf_smooth(0)
	, m_no_stat_begin(0)
	, m_no_stat_tot(0)
	, m_opt_enable(false)
{
	memset(&m_mem, 0, sizeof(m_mem));
}

void Statistics::EnableGraph(bool enable)
{
	if (enable) {
		m_flags |= FLAG_PRINT_GRAPH;
	} else {
		m_flags &= ~FLAG_PRINT_GRAPH;
	}
}

void Statistics::EnableConsole(bool enable)
{
	if (enable) {
		m_flags |= FLAG_PRINT_CONSOLE;
	} else {
		m_flags &= ~FLAG_PRINT_CONSOLE;
	}
}

void Statistics::EnableFile(bool enable)
{
	if (enable == IsFileEnable()) {
		return;
	}

	if (enable)
	{
		m_flags |= FLAG_PRINT_FILE;

#ifdef __ANDROID__
		m_fout.open("/sdcard/lr_stat.bin", std::ofstream::out | std::ofstream::binary);
#else
		m_fout.open("lr_stat.bin", std::ofstream::out | std::ofstream::binary);
#endif // __ANDROID__
	}
	else
	{
		m_flags &= ~FLAG_PRINT_FILE;

		m_fout.close();
	}
}

bool Statistics::IsGraphEnable() const
{
	return (m_flags & FLAG_PRINT_GRAPH) != 0;
}

bool Statistics::IsConsoleEnable() const
{
	return (m_flags & FLAG_PRINT_CONSOLE) != 0;
}

bool Statistics::IsFileEnable() const
{
	return (m_flags & FLAG_PRINT_FILE) != 0;
}

void Statistics::Update()
{
	if (m_flags == 0) {
		return;
	}

	m_tpf = glp_get_dt();
	m_tpf_smooth = (m_tpf_smooth * FPS_SMOOTHING) + m_tpf * (1.0f - FPS_SMOOTHING);
}

void Statistics::Print()
{
	StatTag::Instance()->PrintScreen();

	if (m_flags == 0) {
		return;
	}

	if (m_flags & FLAG_PRINT_GRAPH) {
		PrintScreen();
	}
	if (m_flags & FLAG_PRINT_CONSOLE) {
		PrintConsole();
	}
	if (m_flags & FLAG_PRINT_FILE) {
		PrintFile();
	}
}

void Statistics::Reset()
{
	if (m_flags == 0) {
		return;
	}

	m_tpf = 0;

	sl::Statistics::Instance()->Reset();
	sl::StatDrawCall::Instance()->Reset();

	s2::StatDrawCall::Instance()->Reset();
	s2::StatPingPong::Instance()->Reset();
	s2::StatTopNodes::Instance()->Reset();
	s2::StatSymbol::Instance()->Reset();
}

void Statistics::Flush()
{
	StatTag::Instance()->Flush();
}

void Statistics::NoStatBegin()
{
	m_no_stat_begin = glp_get_time();
}

void Statistics::NoStatEnd()
{
	m_no_stat_tot = (glp_get_time() - m_no_stat_begin);
}

void Statistics::OptEnable(bool enable)
{
	m_opt_enable = enable;
}

void Statistics::SetMem(float tot, float lua)
{
	m_mem.tot = tot;
	m_mem.lua = lua;
}

void Statistics::PrintScreen() const
{
	sl::ShaderMgr* mgr = sl::ShaderMgr::Instance();
	mgr->SetShader(sl::SPRITE2);

	static char buf[512];

	const int w = 960;
	const int top = 280;

	S2_MAT mt;
	mt.Translate(0, top);

	sprintf(buf, "OPT: %s, emitter: %d", m_opt_enable ? "open" : "closed", p3d_emitter_count());
	GTxt::Instance()->Draw(mt, buf, w);

	mt.Translate(0, -30);
	sprintf(buf, "FPS: %.1f, ms: %.1f, ex:%.1f", 1000.0f / m_tpf, m_tpf_smooth, m_no_stat_tot / 1000.0f);
	GTxt::Instance()->Draw(mt, buf, w);

	mt.Translate(0, -30);
	sprintf(buf, "MEM: tot %.1f, tex %.1f, lua %.1f", m_mem.tot, m_mem.tex, m_mem.lua);
	GTxt::Instance()->Draw(mt, buf, w);

	static std::string buf_str;
	buf_str.reserve(512);

	mt.Translate(0, -30);
	sl::Statistics::Instance()->Print(buf_str);
	GTxt::Instance()->Draw(mt, buf_str, w);
	buf_str.clear();

	mt.Translate(0, -30);
	s2::StatDrawCall::Instance()->Print(buf_str);
	GTxt::Instance()->Draw(mt, buf_str, w);
	buf_str.clear();

	mt.Translate(0, -40);
	s2::StatPingPong::Instance()->Print(buf_str);
	GTxt::Instance()->Draw(mt, buf_str, w);
	buf_str.clear();

	mt.Translate(0, -50);
	sprintf(buf, "COUNT: sym %d, spr %d, actor %d, img %d",
		SymbolPool::Instance()->Count(),
		s2::Sprite::GetAllSprCount(),
		s2::Actor::GetAllActorCount(),
		ImageMgr::Instance()->Count());
	GTxt::Instance()->Draw(mt, buf, w);

	mt.Translate(450, -100);
	s2::StatTopNodes::Instance()->Print(buf_str);
	GTxt::Instance()->Draw(mt, buf_str, w);
	buf_str.clear();

// 	mt.Translate(450, 180);
// 	s2::StatSymbol::Instance()->Print(buf_str);
// 	GTxt::Instance()->Draw(mt, buf_str, w);
// 	buf_str.clear();

// 	mt.Translate(0, -230);
// 	sl::StatDrawCall::Instance()->Print(buf_str);
// 	GTxt::Instance()->Draw(mt, buf_str, w);
// 	buf_str.clear();

	mgr->FlushShader();
}

void Statistics::PrintConsole() const
{
	static const int PRINT_COUNT = 30;
	static int count = 0;
	++count;
	if (count == PRINT_COUNT)
	{
		count = 0;
		sl::Statistics* stat = sl::Statistics::Instance();
		int dc = stat->GetDrawCall();
		int count = stat->GetVertices();
		float fps_curr = StatFPS::Instance()->GetFPSCurr();
		float curr_cost = 0;
		if (fps_curr != 0) {
			curr_cost = 1000.0f / fps_curr;
		}
		LOGI("fps %.1f, cost %.1f, dc %d, vertices %d, cost avg %.1f\n",
			1000.0f / m_tpf_smooth, m_tpf_smooth, dc, count, curr_cost);
	}
}

void Statistics::PrintFile() const
{
	sl::Statistics* sl_stat = sl::Statistics::Instance();

	static char buf[512];
	sprintf(buf, "timestamp %lu, cost %.1f, vertices %d, dc %d\n",
		time(NULL), m_tpf_smooth, sl_stat->GetVertices(), sl_stat->GetDrawCall());
	m_fout << buf;

// 	static std::string buf_str;
// 	buf_str.reserve(1024);
// 	s2::StatTopNodes::Instance()->Print(buf_str);
// 	m_fout << buf_str;

	static const int FLUSH_COUNT = 100;
	static int count = 0;
	++count;
	if (count == FLUSH_COUNT) {
		count = 0;
		m_fout.flush();
	}
}

}<|endoftext|>


<commit_before>/*
 * Trajectory class representing a trajectory in state space
 *
 * Author: Andrew Barry, <abarry@csail.mit.edu> 2013-2015
 *
 */

#include "Trajectory.hpp"

// Constructor that loads a trajectory from a file
Trajectory::Trajectory() {
    trajectory_number_ = -1;
    dimension_ = 0;
    udimension_ = 0;
    filename_prefix_ = "";
    dt_ = 0;
}

Trajectory::Trajectory(std::string filename_prefix, bool quiet) : Trajectory() {
    LoadTrajectory(filename_prefix, quiet);
}

void Trajectory::LoadTrajectory(std::string filename_prefix, bool quiet) {
    // open the file
    std::vector<std::vector<std::string>> strs;

    if (!quiet)
    {
        std::cout << "Loading trajectory: " << std::endl << "\t" << filename_prefix << std::endl;
    }

    std::string traj_number_str = filename_prefix.substr(filename_prefix.length() - 5, 5);
    trajectory_number_ = std::stoi(traj_number_str);

    LoadMatrixFromCSV(filename_prefix + "-x.csv", xpoints_, quiet);
    LoadMatrixFromCSV(filename_prefix + "-u.csv", upoints_, quiet);
    LoadMatrixFromCSV(filename_prefix + "-controller.csv", kpoints_, quiet);
    LoadMatrixFromCSV(filename_prefix + "-affine.csv", affine_points_, quiet);

    filename_prefix_ = filename_prefix;

    dimension_ = xpoints_.cols() - 1; // minus 1 because of time index
    udimension_ = upoints_.cols() - 1;

    if (kpoints_.cols() - 1 != dimension_ * udimension_) {
        std::cerr << "Error: expected to have " << dimension_ << "*" << udimension_ << "+1 = " << dimension_ * udimension_ + 1 << " columns in " << filename_prefix << "-controller.csv but found " << kpoints_.cols() << std::endl;
        exit(1);
    }

    if (affine_points_.cols() - 1 != udimension_) {
        std::cerr << "Error: expected to have " << udimension_ << "+1 = " << udimension_ + 1 << " columns in " << filename_prefix << "-affine.csv but found " << affine_points_.cols() << std::endl;
        exit(1);
    }

    if (upoints_.rows() != kpoints_.rows() || upoints_.rows() != affine_points_.rows()) {
        std::cerr << "Error: inconsistent number of rows in CSV files: " << std::endl
            << "\t" << filename_prefix << "-x: " << xpoints_.rows() << std::endl
            << "\t" << filename_prefix << "-u: " << upoints_.rows() << std::endl
            << "\t" << filename_prefix << "-controller: " << kpoints_.rows() << std::endl
            << "\t" << filename_prefix << "-affine: " << affine_points_.rows() << std::endl;

            exit(1);
    }

    // set the minimum altitude
    BotTrans trans;
    bot_trans_set_identity(&trans);
    bool first_run = true;

    for (int i = 0; i < GetNumberOfPoints(); i++) {

        double this_t = GetTimeAtIndex(i);
        double xyz[3];

        GetXyzYawTransformedPoint(this_t, trans, xyz);

        if (xyz[2] < min_altitude_ || first_run == true) {
            min_altitude_ = xyz[2];
            first_run = false;
        }
    }
}

void Trajectory::LoadMatrixFromCSV( const std::string& filename, Eigen::MatrixXd &matrix, bool quiet) {

    if (!quiet) {
        std::cout << "Loading " << filename << std::endl;
    }

    int number_of_lines = GetNumberOfLines(filename);
    int row_num = 0;

    int i =  0;
    //                                   file, delimiter, first_line_is_header?
    CsvParser *csvparser = CsvParser_new(filename.c_str(), ",", true);
    CsvRow *header;
    CsvRow *row;

    header = CsvParser_getHeader(csvparser);
    if (header == NULL) {
        printf("%s\n", CsvParser_getErrorMessage(csvparser));
        return;
    }

    // note: do not remove the getFields(header) call as it has
    // side effects we need even if we don't use the headers
    //char **headerFields = CsvParser_getFields(header);
    CsvParser_getFields(header);
    for (i = 0 ; i < CsvParser_getNumFields(header) ; i++) {
        //printf("TITLE: %s\n", headerFields[i]);
    }

    matrix.resize(number_of_lines - 1, i); // minus 1 for header, i = number of columns

    while ((row = CsvParser_getRow(csvparser)) ) {
        //printf("NEW LINE:\n");
        char **rowFields = CsvParser_getFields(row);
        for (i = 0 ; i < CsvParser_getNumFields(row) ; i++) {

            matrix(row_num, i) = atof(rowFields[i]);

            //printf("FIELD: %20.20f\n", atof(rowFields[i]));
        }
        CsvParser_destroy_row(row);

        if (row_num == 1) {
            dt_ = matrix(1, 0) - matrix(0, 0);
        } else if (row_num > 1) {
            if (matrix(row_num, 0) - matrix(row_num - 1, 0) - dt_ > 5*std::numeric_limits<double>::epsilon()) {
                std::cerr << "Error: non-constant dt. Expected dt = " << dt_ << " but got matrix[" << row_num << "][0] - matrix[" << row_num - 1 << "][0] = " << matrix(row_num, 0) - matrix(row_num - 1, 0) << " (residual = " << (matrix(row_num, 0) - matrix(row_num - 1, 0) - dt_) << std::endl;

                std::cout << matrix << std::endl;
                exit(1);
            }
        }

        row_num ++;
    }
    CsvParser_destroy(csvparser);

}

int Trajectory::GetNumberOfLines(std::string filename) const {
    int number_of_lines = 0;
    std::string line;
    std::ifstream myfile(filename);

    while (getline(myfile, line)) {
        ++number_of_lines;
    }

    return number_of_lines;
}

Eigen::VectorXd Trajectory::GetState(double t) const {
    int index = GetIndexAtTime(t);
    Eigen::VectorXd row_vec = xpoints_.row(index);

    return row_vec.tail(xpoints_.cols() - 1); // remove time
}

Eigen::VectorXd Trajectory::GetUCommand(double t) const {
    int index = GetIndexAtTime(t);

    Eigen::VectorXd row_vec = upoints_.row(index);

    return row_vec.tail(upoints_.cols() - 1); // remove time
}

/**
 * Assuming a constant dt, we can compute the index of a point
 * based on its time.
 *
 * @param t time to find index of
 * @param (optional) use_rollout set to true to use time bounds from rollout instead of xpoints
 * @retval index of nearest point
 */
int Trajectory::GetIndexAtTime(double t) const {

    // round t to the nearest dt_

   double t0, tf;

    t0 = xpoints_(0,0);
    tf = xpoints_(xpoints_.rows() - 1, 0);

   if (t <= t0) {
       return 0;
   } else if (t >= tf) {

        return xpoints_.rows() - 1;
   }
//std::cout << "after" << std::endl;
   // otherwise, we are somewhere in the bounds of the trajectory
    int num_dts = std::round(t/dt_);
    float remainder = std::remainder(t, dt_);
//std::cout << "t = " << t << " remainder = " << remainder << " num_dts = " << num_dts << std::endl;
    if (remainder > 0.5f*dt_) {
        num_dts++;
    }

    int starting_dts = t0 / dt_;

    return num_dts + starting_dts;

}

TEST(Trajectory, GetIndexAtTimeTest) {
    Trajectory traj("trajtest/ti/TI-test-TI-straight-pd-no-yaw-00000", true);

    EXPECT_EQ_ARM(traj.GetIndexAtTime(0), 0);

    EXPECT_EQ_ARM(traj.GetMaxTime(), 3);
    EXPECT_EQ_ARM(traj.GetNumberOfPoints(), 301);
    EXPECT_EQ_ARM(traj.GetIndexAtTime(1000), 300);

    EXPECT_EQ_ARM(traj.GetIndexAtTime(0.0001), 0);

    EXPECT_EQ_ARM(traj.GetIndexAtTime(0.01), 1);

    EXPECT_EQ_ARM(traj.GetIndexAtTime(0.02), 2);

    EXPECT_EQ_ARM(traj.GetIndexAtTime(0.019), 2);

    EXPECT_EQ_ARM(traj.GetIndexAtTime(0.021), 2);

    EXPECT_EQ_ARM(traj.GetIndexAtTime(0.90), 90);

}

/**
 * Unpacks the gain matrix for a specific time t.
 *
 * This could be pre-computed if it becomes a performance bottleneck.
 *
 * @param t time along the trajectory
 *
 * @retval gain matrix at that time with dimension: state_dimension x u_dimension
 */
Eigen::MatrixXd Trajectory::GetGainMatrix(double t) const {
    int index = GetIndexAtTime(t);

    Eigen::VectorXd k_row = kpoints_.row(index);

    Eigen::MatrixXd k_mat(udimension_, dimension_);

    for (int i = 0; i < udimension_; i++) {

        // +1 because the column index is time
        int start_pos = i * dimension_ + 1;

        k_mat.row(i) = k_row.segment(start_pos, dimension_);
    }

    return k_mat;

}

void Trajectory::Print() const {
    std::cout << "------------ Trajectory print -------------" << std::endl;
    std::cout << "Filename: " << filename_prefix_ << std::endl;
    std::cout << "Trajectory number: " << trajectory_number_ << std::endl;
    std::cout << "Dimension: " << dimension_ << std::endl;
    std::cout << "u-dimension: " << udimension_ << std::endl;

    std::cout << " t\t x\t y\t z\t roll\t pitch\t yaw \t xdot\t ydot\t zdot\t rolld\t pitchd\t yawd" << std::endl;

    std::cout << xpoints_ << std::endl;

    std::cout << "------------- u points ----------------" << std::endl;

    std::cout << " t\t u1\t u2\t u3" << std::endl;

    std::cout << upoints_ << std::endl;

    std::cout << "------------- k points ----------------" << std::endl;

    std::cout << kpoints_ << std::endl;

    std::cout << "------------- affine points ----------------" << std::endl;

    std::cout << affine_points_ << std::endl;
}

/**
 * Returns a point along the trajectory transformed with xyz and yaw.  Ignores pitch and roll.
 */
void Trajectory::GetXyzYawTransformedPoint(double t, const BotTrans &transform, double *xyz) const {
    // apply the transformation from the global frame: orgin = (0,0,0)
    // to the local frame point

    Eigen::VectorXd state = GetState(t);

    double original_point[3];
    original_point[0] = state(0);
    original_point[1] = state(1);
    original_point[2] = state(2);

    // remove roll and pitch from the transform
    BotTrans trans_xyz_yaw;

    bot_trans_copy(&trans_xyz_yaw, &transform);

    double rpy[3];
    bot_quat_to_roll_pitch_yaw(trans_xyz_yaw.rot_quat, rpy);

    rpy[0] = 0;
    rpy[1] = 0;

    bot_roll_pitch_yaw_to_quat(rpy, trans_xyz_yaw.rot_quat);

    bot_trans_apply_vec(&trans_xyz_yaw, original_point, xyz);

}

void Trajectory::Draw(bot_lcmgl_t *lcmgl, const BotTrans *transform) const {
    if (transform == nullptr) {
        BotTrans temp_trans;
        bot_trans_set_identity(&temp_trans);
        transform = &temp_trans;
    }

    // draw the trajectory's origin
    double xyz[3];
    float origin_size[3] = { .25, .25, .25 };

    GetXyzYawTransformedPoint(0, *transform, xyz);

    bot_lcmgl_box(lcmgl, xyz, origin_size);

    bot_lcmgl_line_width(lcmgl, 2.0f);

    bot_lcmgl_begin(lcmgl, GL_LINE_STRIP);
    double t = 0;
    while (t < GetMaxTime()) {
        GetXyzYawTransformedPoint(t, *transform, xyz);

        bot_lcmgl_vertex3f(lcmgl, xyz[0], xyz[1], xyz[2]);
        t += GetDT();
    }
    bot_lcmgl_end(lcmgl);

    t = 0;
    while (t < GetMaxTime()) {
        GetXyzYawTransformedPoint(t, *transform, xyz);

        bot_lcmgl_sphere(lcmgl, xyz, 0.05, 20, 20);

        t += GetDT();
    }

    // label the last point with a timestamp
    //char t_end[50];
    //sprintf(t_end, "t = %.2fs", GetMaxTime());
    //bot_lcmgl_text_ex(lcmgl, xyz, t_end, 0,
        //BOT_GL_DRAW_TEXT_JUSTIFY_CENTER |
        //BOT_GL_DRAW_TEXT_ANCHOR_HCENTER |
        //BOT_GL_DRAW_TEXT_ANCHOR_VCENTER);

}

/**
 * Searches along the remainder of the trajectory, assuming it executes exactly from the
 * current position.
 *
 * Returns the distance to the closest obstacle over that search.  Used for determining if
 * replanning is required
 *
 * @param octomap Obstacle map
 * @param bodyToLocal Current position of the aircraft
 * @param current_t Time along the trajectory
 *
 * @retval Distance to the closest obstacle along the remainder of the trajectory
 */
double Trajectory::ClosestObstacleInRemainderOfTrajectory(const StereoOctomap &octomap, const BotTrans &body_to_local, double current_t) const {

    // for each point remaining in the trajectory
    int number_of_points = GetNumberOfPoints();

    int starting_index = GetIndexAtTime(current_t);
    std::vector<double> point_distances(number_of_points); // TODO: potentially inefficient
    double closest_obstacle_distance = -1;

    for (int i = starting_index; i < number_of_points; i++) {
        // for each point in the trajectory

        // subtract the current position (ie move the trajectory to where we are)
        double transformed_point[3];

        double this_t = GetTimeAtIndex(i);

        GetXyzYawTransformedPoint(this_t, body_to_local, transformed_point);

        // check if there is an obstacle nearby
        point_distances.at(i) = octomap.NearestNeighbor(transformed_point);

    }

    for (int i = starting_index; i < number_of_points; i++) {
        double distance_to_point = point_distances.at(i);
        if (distance_to_point >= 0) {
            if (distance_to_point < closest_obstacle_distance || closest_obstacle_distance < 0) {
                closest_obstacle_distance = distance_to_point;
            }
        }
    }

     // check minumum altitude
    double min_altitude = GetMinimumAltitude() + body_to_local.trans_vec[2];
    if (min_altitude < 0) {
        // this trajectory would impact the ground
        closest_obstacle_distance = 0;
    } else if (min_altitude < closest_obstacle_distance || closest_obstacle_distance < 0) {
        closest_obstacle_distance = min_altitude;
    }

    return closest_obstacle_distance;
}
<commit_msg>altitude fix<commit_after>/*
 * Trajectory class representing a trajectory in state space
 *
 * Author: Andrew Barry, <abarry@csail.mit.edu> 2013-2015
 *
 */

#include "Trajectory.hpp"

// Constructor that loads a trajectory from a file
Trajectory::Trajectory() {
    trajectory_number_ = -1;
    dimension_ = 0;
    udimension_ = 0;
    filename_prefix_ = "";
    dt_ = 0;
}

Trajectory::Trajectory(std::string filename_prefix, bool quiet) : Trajectory() {
    LoadTrajectory(filename_prefix, quiet);
}

void Trajectory::LoadTrajectory(std::string filename_prefix, bool quiet) {
    // open the file
    std::vector<std::vector<std::string>> strs;

    if (!quiet)
    {
        std::cout << "Loading trajectory: " << std::endl << "\t" << filename_prefix << std::endl;
    }

    std::string traj_number_str = filename_prefix.substr(filename_prefix.length() - 5, 5);
    trajectory_number_ = std::stoi(traj_number_str);

    LoadMatrixFromCSV(filename_prefix + "-x.csv", xpoints_, quiet);
    LoadMatrixFromCSV(filename_prefix + "-u.csv", upoints_, quiet);
    LoadMatrixFromCSV(filename_prefix + "-controller.csv", kpoints_, quiet);
    LoadMatrixFromCSV(filename_prefix + "-affine.csv", affine_points_, quiet);

    filename_prefix_ = filename_prefix;

    dimension_ = xpoints_.cols() - 1; // minus 1 because of time index
    udimension_ = upoints_.cols() - 1;

    if (kpoints_.cols() - 1 != dimension_ * udimension_) {
        std::cerr << "Error: expected to have " << dimension_ << "*" << udimension_ << "+1 = " << dimension_ * udimension_ + 1 << " columns in " << filename_prefix << "-controller.csv but found " << kpoints_.cols() << std::endl;
        exit(1);
    }

    if (affine_points_.cols() - 1 != udimension_) {
        std::cerr << "Error: expected to have " << udimension_ << "+1 = " << udimension_ + 1 << " columns in " << filename_prefix << "-affine.csv but found " << affine_points_.cols() << std::endl;
        exit(1);
    }

    if (upoints_.rows() != kpoints_.rows() || upoints_.rows() != affine_points_.rows()) {
        std::cerr << "Error: inconsistent number of rows in CSV files: " << std::endl
            << "\t" << filename_prefix << "-x: " << xpoints_.rows() << std::endl
            << "\t" << filename_prefix << "-u: " << upoints_.rows() << std::endl
            << "\t" << filename_prefix << "-controller: " << kpoints_.rows() << std::endl
            << "\t" << filename_prefix << "-affine: " << affine_points_.rows() << std::endl;

            exit(1);
    }

    // set the minimum altitude
    BotTrans trans;
    bot_trans_set_identity(&trans);
    bool first_run = true;

    for (int i = 0; i < GetNumberOfPoints(); i++) {

        double this_t = GetTimeAtIndex(i);
        double xyz[3];

        GetXyzYawTransformedPoint(this_t, trans, xyz);

        if (xyz[2] < min_altitude_ || first_run == true) {
            min_altitude_ = xyz[2];
            first_run = false;
        }
    }
}

void Trajectory::LoadMatrixFromCSV( const std::string& filename, Eigen::MatrixXd &matrix, bool quiet) {

    if (!quiet) {
        std::cout << "Loading " << filename << std::endl;
    }

    int number_of_lines = GetNumberOfLines(filename);
    int row_num = 0;

    int i =  0;
    //                                   file, delimiter, first_line_is_header?
    CsvParser *csvparser = CsvParser_new(filename.c_str(), ",", true);
    CsvRow *header;
    CsvRow *row;

    header = CsvParser_getHeader(csvparser);
    if (header == NULL) {
        printf("%s\n", CsvParser_getErrorMessage(csvparser));
        return;
    }

    // note: do not remove the getFields(header) call as it has
    // side effects we need even if we don't use the headers
    //char **headerFields = CsvParser_getFields(header);
    CsvParser_getFields(header);
    for (i = 0 ; i < CsvParser_getNumFields(header) ; i++) {
        //printf("TITLE: %s\n", headerFields[i]);
    }

    matrix.resize(number_of_lines - 1, i); // minus 1 for header, i = number of columns

    while ((row = CsvParser_getRow(csvparser)) ) {
        //printf("NEW LINE:\n");
        char **rowFields = CsvParser_getFields(row);
        for (i = 0 ; i < CsvParser_getNumFields(row) ; i++) {

            matrix(row_num, i) = atof(rowFields[i]);

            //printf("FIELD: %20.20f\n", atof(rowFields[i]));
        }
        CsvParser_destroy_row(row);

        if (row_num == 1) {
            dt_ = matrix(1, 0) - matrix(0, 0);
        } else if (row_num > 1) {
            if (matrix(row_num, 0) - matrix(row_num - 1, 0) - dt_ > 5*std::numeric_limits<double>::epsilon()) {
                std::cerr << "Error: non-constant dt. Expected dt = " << dt_ << " but got matrix[" << row_num << "][0] - matrix[" << row_num - 1 << "][0] = " << matrix(row_num, 0) - matrix(row_num - 1, 0) << " (residual = " << (matrix(row_num, 0) - matrix(row_num - 1, 0) - dt_) << std::endl;

                std::cout << matrix << std::endl;
                exit(1);
            }
        }

        row_num ++;
    }
    CsvParser_destroy(csvparser);

}

int Trajectory::GetNumberOfLines(std::string filename) const {
    int number_of_lines = 0;
    std::string line;
    std::ifstream myfile(filename);

    while (getline(myfile, line)) {
        ++number_of_lines;
    }

    return number_of_lines;
}

Eigen::VectorXd Trajectory::GetState(double t) const {
    int index = GetIndexAtTime(t);
    Eigen::VectorXd row_vec = xpoints_.row(index);

    return row_vec.tail(xpoints_.cols() - 1); // remove time
}

Eigen::VectorXd Trajectory::GetUCommand(double t) const {
    int index = GetIndexAtTime(t);

    Eigen::VectorXd row_vec = upoints_.row(index);

    return row_vec.tail(upoints_.cols() - 1); // remove time
}

/**
 * Assuming a constant dt, we can compute the index of a point
 * based on its time.
 *
 * @param t time to find index of
 * @param (optional) use_rollout set to true to use time bounds from rollout instead of xpoints
 * @retval index of nearest point
 */
int Trajectory::GetIndexAtTime(double t) const {

    // round t to the nearest dt_

   double t0, tf;

    t0 = xpoints_(0,0);
    tf = xpoints_(xpoints_.rows() - 1, 0);

   if (t <= t0) {
       return 0;
   } else if (t >= tf) {

        return xpoints_.rows() - 1;
   }
//std::cout << "after" << std::endl;
   // otherwise, we are somewhere in the bounds of the trajectory
    int num_dts = std::round(t/dt_);
    float remainder = std::remainder(t, dt_);
//std::cout << "t = " << t << " remainder = " << remainder << " num_dts = " << num_dts << std::endl;
    if (remainder > 0.5f*dt_) {
        num_dts++;
    }

    int starting_dts = t0 / dt_;

    return num_dts + starting_dts;

}

TEST(Trajectory, GetIndexAtTimeTest) {
    Trajectory traj("trajtest/ti/TI-test-TI-straight-pd-no-yaw-00000", true);

    EXPECT_EQ_ARM(traj.GetIndexAtTime(0), 0);

    EXPECT_EQ_ARM(traj.GetMaxTime(), 3);
    EXPECT_EQ_ARM(traj.GetNumberOfPoints(), 301);
    EXPECT_EQ_ARM(traj.GetIndexAtTime(1000), 300);

    EXPECT_EQ_ARM(traj.GetIndexAtTime(0.0001), 0);

    EXPECT_EQ_ARM(traj.GetIndexAtTime(0.01), 1);

    EXPECT_EQ_ARM(traj.GetIndexAtTime(0.02), 2);

    EXPECT_EQ_ARM(traj.GetIndexAtTime(0.019), 2);

    EXPECT_EQ_ARM(traj.GetIndexAtTime(0.021), 2);

    EXPECT_EQ_ARM(traj.GetIndexAtTime(0.90), 90);

}

/**
 * Unpacks the gain matrix for a specific time t.
 *
 * This could be pre-computed if it becomes a performance bottleneck.
 *
 * @param t time along the trajectory
 *
 * @retval gain matrix at that time with dimension: state_dimension x u_dimension
 */
Eigen::MatrixXd Trajectory::GetGainMatrix(double t) const {
    int index = GetIndexAtTime(t);

    Eigen::VectorXd k_row = kpoints_.row(index);

    Eigen::MatrixXd k_mat(udimension_, dimension_);

    for (int i = 0; i < udimension_; i++) {

        // +1 because the column index is time
        int start_pos = i * dimension_ + 1;

        k_mat.row(i) = k_row.segment(start_pos, dimension_);
    }

    return k_mat;

}

void Trajectory::Print() const {
    std::cout << "------------ Trajectory print -------------" << std::endl;
    std::cout << "Filename: " << filename_prefix_ << std::endl;
    std::cout << "Trajectory number: " << trajectory_number_ << std::endl;
    std::cout << "Dimension: " << dimension_ << std::endl;
    std::cout << "u-dimension: " << udimension_ << std::endl;

    std::cout << " t\t x\t y\t z\t roll\t pitch\t yaw \t xdot\t ydot\t zdot\t rolld\t pitchd\t yawd" << std::endl;

    std::cout << xpoints_ << std::endl;

    std::cout << "------------- u points ----------------" << std::endl;

    std::cout << " t\t u1\t u2\t u3" << std::endl;

    std::cout << upoints_ << std::endl;

    std::cout << "------------- k points ----------------" << std::endl;

    std::cout << kpoints_ << std::endl;

    std::cout << "------------- affine points ----------------" << std::endl;

    std::cout << affine_points_ << std::endl;
}

/**
 * Returns a point along the trajectory transformed with xyz and yaw.  Ignores pitch and roll.
 */
void Trajectory::GetXyzYawTransformedPoint(double t, const BotTrans &transform, double *xyz) const {
    // apply the transformation from the global frame: orgin = (0,0,0)
    // to the local frame point

    Eigen::VectorXd state = GetState(t);

    double original_point[3];
    original_point[0] = state(0);
    original_point[1] = state(1);
    original_point[2] = state(2);

    // remove roll and pitch from the transform
    BotTrans trans_xyz_yaw;

    bot_trans_copy(&trans_xyz_yaw, &transform);

    double rpy[3];
    bot_quat_to_roll_pitch_yaw(trans_xyz_yaw.rot_quat, rpy);

    rpy[0] = 0;
    rpy[1] = 0;

    bot_roll_pitch_yaw_to_quat(rpy, trans_xyz_yaw.rot_quat);

    bot_trans_apply_vec(&trans_xyz_yaw, original_point, xyz);

}

void Trajectory::Draw(bot_lcmgl_t *lcmgl, const BotTrans *transform) const {
    if (transform == nullptr) {
        BotTrans temp_trans;
        bot_trans_set_identity(&temp_trans);
        transform = &temp_trans;
    }

    // draw the trajectory's origin
    double xyz[3];
    float origin_size[3] = { .25, .25, .25 };

    GetXyzYawTransformedPoint(0, *transform, xyz);

    bot_lcmgl_box(lcmgl, xyz, origin_size);

    bot_lcmgl_line_width(lcmgl, 2.0f);

    bot_lcmgl_begin(lcmgl, GL_LINE_STRIP);
    double t = 0;
    while (t < GetMaxTime()) {
        GetXyzYawTransformedPoint(t, *transform, xyz);

        bot_lcmgl_vertex3f(lcmgl, xyz[0], xyz[1], xyz[2]);
        t += GetDT();
    }
    bot_lcmgl_end(lcmgl);

    t = 0;
    while (t < GetMaxTime()) {
        GetXyzYawTransformedPoint(t, *transform, xyz);

        bot_lcmgl_sphere(lcmgl, xyz, 0.05, 20, 20);

        t += GetDT();
    }

    // label the last point with a timestamp
    //char t_end[50];
    //sprintf(t_end, "t = %.2fs", GetMaxTime());
    //bot_lcmgl_text_ex(lcmgl, xyz, t_end, 0,
        //BOT_GL_DRAW_TEXT_JUSTIFY_CENTER |
        //BOT_GL_DRAW_TEXT_ANCHOR_HCENTER |
        //BOT_GL_DRAW_TEXT_ANCHOR_VCENTER);

}

/**
 * Searches along the remainder of the trajectory, assuming it executes exactly from the
 * current position.
 *
 * Returns the distance to the closest obstacle over that search.  Used for determining if
 * replanning is required
 *
 * @param octomap Obstacle map
 * @param bodyToLocal Current position of the aircraft
 * @param current_t Time along the trajectory
 *
 * @retval Distance to the closest obstacle along the remainder of the trajectory
 */
double Trajectory::ClosestObstacleInRemainderOfTrajectory(const StereoOctomap &octomap, const BotTrans &body_to_local, double current_t) const {

    // for each point remaining in the trajectory
    int number_of_points = GetNumberOfPoints();

    int starting_index = GetIndexAtTime(current_t);
    std::vector<double> point_distances(number_of_points); // TODO: potentially inefficient
    double closest_obstacle_distance = -1;

    for (int i = starting_index; i < number_of_points; i++) {
        // for each point in the trajectory

        // subtract the current position (ie move the trajectory to where we are)
        double transformed_point[3];

        double this_t = GetTimeAtIndex(i);

        GetXyzYawTransformedPoint(this_t, body_to_local, transformed_point);

        // check if there is an obstacle nearby
        point_distances.at(i) = octomap.NearestNeighbor(transformed_point);

    }

    for (int i = starting_index; i < number_of_points; i++) {
        double distance_to_point = point_distances.at(i);
        if (distance_to_point >= 0) {
            if (distance_to_point < closest_obstacle_distance || closest_obstacle_distance < 0) {
                closest_obstacle_distance = distance_to_point;
            }
        }
    }

     // check minumum altitude
    double min_altitude = GetMinimumAltitude() + body_to_local.trans_vec[2];
    if (min_altitude < 0) { //// TODO FIXME HACK SHOULD BE A PARAM
        // this trajectory would impact the ground
        closest_obstacle_distance = 0;
    }// else if (min_altitude < closest_obstacle_distance || closest_obstacle_distance < 0) {
     //   closest_obstacle_distance = min_altitude;
    //}

    return closest_obstacle_distance;
}
<|endoftext|>


<commit_before>#include "movable_entity.h"

#include <iostream> // TODO remove!
#include <algorithm>

using namespace space_invaders;

MovableEntity::MovableEntity(Game& game)
  : DrawableEntity(game),
    mStepSize(0),
    mStepCounter(0),
    mVelocity(0.f),
    mDirectionX(0.f),
    mDirectionY(0.f)
{
  // ...
}

void MovableEntity::update(unsigned long dt)
{
  DrawableEntity::update(dt);
  mStepCounter = std::max(0, mStepCounter - 1);
  if (mStepCounter <= 0) {
    this->setX(this->getX() + mDirectionX * mVelocity * dt);
    this->setY(this->getY() + mDirectionY * mVelocity * dt);
    mStepCounter = mStepSize;
  }
}

void MovableEntity::setStepSize(int stepSize)
{
  mStepSize = stepSize;
  mStepCounter = stepSize;
}<commit_msg>Removed the unnecessary #include <iostream> from the movable_entity.cpp<commit_after>#include "movable_entity.h"

#include <algorithm>

using namespace space_invaders;

MovableEntity::MovableEntity(Game& game)
  : DrawableEntity(game),
    mStepSize(0),
    mStepCounter(0),
    mVelocity(0.f),
    mDirectionX(0.f),
    mDirectionY(0.f)
{
  // ...
}

void MovableEntity::update(unsigned long dt)
{
  DrawableEntity::update(dt);
  mStepCounter = std::max(0, mStepCounter - 1);
  if (mStepCounter <= 0) {
    this->setX(this->getX() + mDirectionX * mVelocity * dt);
    this->setY(this->getY() + mDirectionY * mVelocity * dt);
    mStepCounter = mStepSize;
  }
}

void MovableEntity::setStepSize(int stepSize)
{
  mStepSize = stepSize;
  mStepCounter = stepSize;
}<|endoftext|>


<commit_before>#include "utils/rename-existing/rename-existing-2.h"
#include <QDir>
#include <QFile>
#include <ui_rename-existing-2.h>
#include "functions.h"
#include "logger.h"
#include "rename-existing-table-model.h"

RenameExisting2::RenameExisting2(QList<RenameExistingFile> details, QString folder, QWidget *parent)
	: QDialog(parent), ui(new Ui::RenameExisting2), m_details(std::move(details)), m_folder(std::move(folder))
{
	ui->setupUi(this);

	m_model = new RenameExistingTableModel(m_details, m_folder, this);
	ui->tableView->setModel(m_model);

	QHeaderView *verticalHeader = ui->tableView->verticalHeader();
	verticalHeader->setSectionResizeMode(QHeaderView::Fixed);
	verticalHeader->setDefaultSectionSize(50);

	QHeaderView *headerView = ui->tableView->horizontalHeader();
	headerView->setSectionResizeMode(QHeaderView::Interactive);
	headerView->resizeSection(0, 50);
	headerView->setSectionResizeMode(1, QHeaderView::Stretch);
	headerView->setSectionResizeMode(2, QHeaderView::Stretch);
}

RenameExisting2::~RenameExisting2()
{
	delete ui;
}

void RenameExisting2::on_buttonCancel_clicked()
{
	emit rejected();
	close();
}

void RenameExisting2::deleteDir(const QString &path)
{
	if (path == m_folder) {
		return;
	}

	QDir directory(path);
	if (directory.entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).count() == 0) {
		directory.removeRecursively();

		const QString parent = path.left(path.lastIndexOf(QDir::separator()));
		deleteDir(parent);
	}
}

void RenameExisting2::on_buttonOk_clicked()
{
	// Move all images
	for (const RenameExistingFile &image : qAsConst(m_details)) {
		// Ignore images with no change in path
		if (image.newPath.isEmpty() || image.newPath == image.path) {
			continue;
		}

		// Create hierarchy
		const QString path = image.newPath.left(image.newPath.lastIndexOf(QDir::separator()));
		QDir directory(path);
		if (!directory.exists()) {
			QDir dir;
			if (!dir.mkpath(path)) {
				log(QStringLiteral("Could not create destination directory"), Logger::Error);
			}
		}

		// Move file
		QFile::rename(image.path, image.newPath);
		for (const QString &child : image.children) {
			const QString newPath = QString(child).replace(image.path, image.newPath);
			QFile::rename(child, newPath);
		}

		// Delete old path if necessary
		const QString oldDir = image.path.left(image.path.lastIndexOf(QDir::separator()));
		deleteDir(oldDir);
	}

	// Close
	emit accepted();
	close();
}
<commit_msg>Add warnings when image renamer failed to rename a file<commit_after>#include "utils/rename-existing/rename-existing-2.h"
#include <QDir>
#include <QFile>
#include <ui_rename-existing-2.h>
#include "functions.h"
#include "logger.h"
#include "rename-existing-table-model.h"

RenameExisting2::RenameExisting2(QList<RenameExistingFile> details, QString folder, QWidget *parent)
	: QDialog(parent), ui(new Ui::RenameExisting2), m_details(std::move(details)), m_folder(std::move(folder))
{
	ui->setupUi(this);

	m_model = new RenameExistingTableModel(m_details, m_folder, this);
	ui->tableView->setModel(m_model);

	QHeaderView *verticalHeader = ui->tableView->verticalHeader();
	verticalHeader->setSectionResizeMode(QHeaderView::Fixed);
	verticalHeader->setDefaultSectionSize(50);

	QHeaderView *headerView = ui->tableView->horizontalHeader();
	headerView->setSectionResizeMode(QHeaderView::Interactive);
	headerView->resizeSection(0, 50);
	headerView->setSectionResizeMode(1, QHeaderView::Stretch);
	headerView->setSectionResizeMode(2, QHeaderView::Stretch);
}

RenameExisting2::~RenameExisting2()
{
	delete ui;
}

void RenameExisting2::on_buttonCancel_clicked()
{
	emit rejected();
	close();
}

void RenameExisting2::deleteDir(const QString &path)
{
	if (path == m_folder) {
		return;
	}

	QDir directory(path);
	if (directory.entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).count() == 0) {
		directory.removeRecursively();

		const QString parent = path.left(path.lastIndexOf(QDir::separator()));
		deleteDir(parent);
	}
}

void RenameExisting2::on_buttonOk_clicked()
{
	// Move all images
	for (const RenameExistingFile &image : qAsConst(m_details)) {
		// Ignore images with no change in path
		if (image.newPath.isEmpty() || image.newPath == image.path) {
			continue;
		}

		// Create hierarchy
		const QString path = image.newPath.left(image.newPath.lastIndexOf(QDir::separator()));
		QDir directory(path);
		if (!directory.exists()) {
			QDir dir;
			if (!dir.mkpath(path)) {
				log(QStringLiteral("Could not create destination directory"), Logger::Error);
			}
		}

		// Move file
		if (!QFile::rename(image.path, image.newPath)) {
			log(QStringLiteral("Could not rename file from `%1` to `%2`").arg(image.path, image.newPath), Logger::Error);
		}
		for (const QString &child : image.children) {
			const QString newPath = QString(child).replace(image.path, image.newPath);
			if (!QFile::rename(child, newPath)) {
				log(QStringLiteral("Could not rename child file from `%1` to `%2`").arg(image.path, image.newPath), Logger::Error);
			}
		}

		// Delete old path if necessary
		const QString oldDir = image.path.left(image.path.lastIndexOf(QDir::separator()));
		deleteDir(oldDir);
	}

	// Close
	emit accepted();
	close();
}
<|endoftext|>