<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"

#if defined(OS_MACOSX)
#include <CoreGraphics/CGDisplayConfiguration.h>
#endif

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/string_number_conversions.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/gfx/gl/gl_implementation.h"
#include "ui/gfx/gl/gl_switches.h"
#include "webkit/plugins/plugin_switches.h"

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

namespace {

#if defined(OS_MACOSX)
void DisplayReconfigCallback(CGDirectDisplayID display,
                             CGDisplayChangeSummaryFlags flags,
                             void* gpu_data_manager) {
  // TODO(zmo): this logging is temporary for crbug 88008 and will be removed.
  LOG(INFO) << "Display re-configuration: flags = 0x"
            << base::StringPrintf("%04x", flags);
  if (flags & kCGDisplayAddFlag) {
    GpuDataManagerImpl* manager =
        reinterpret_cast<GpuDataManagerImpl*>(gpu_data_manager);
    DCHECK(manager);
    manager->HandleGpuSwitch();
  }
}
#endif

}  // namespace anonymous

// 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 defined(OS_MACOSX)
  CGDisplayRegisterReconfigurationCallback(DisplayReconfigCallback, this);
#endif
}

GpuDataManagerImpl::~GpuDataManagerImpl() {
#if defined(OS_MACOSX)
  CGDisplayRemoveReconfigurationCallback(DisplayReconfigCallback, this);
#endif
}

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));

  complete_gpu_info_available_ =
      complete_gpu_info_available_ || gpu_info.finalized;
  complete_gpu_info_already_requested_ =
      complete_gpu_info_already_requested_ || gpu_info.finalized;
  {
    base::AutoLock auto_lock(gpu_info_lock_);
    if (!Merge(&gpu_info_, gpu_info))
      return;
    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;

  // 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);
  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");
    command_line->AppendSwitchPath(switches::kSwiftShaderPath,
                                   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);
  }

  {
    base::AutoLock auto_lock(gpu_info_lock_);
    if (gpu_info_.optimus)
      command_line->AppendSwitch(switches::kReduceGpuSandbox);
  }
}

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

void GpuDataManagerImpl::HandleGpuSwitch() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  content::GPUInfo gpu_info;
  gpu_info_collector::CollectVideoCardInfo(&gpu_info);
  LOG(INFO) << "Switching to use GPU: vendor_id = 0x"
            << base::StringPrintf("%04x", gpu_info.vendor_id)
            << ", device_id = 0x"
            << base::StringPrintf("%04x", gpu_info.device_id);
  // TODO(zmo): update gpu_info_, re-run blacklist logic, maybe close and
  // relaunch GPU process.
}

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;

  {
    base::AutoLock auto_lock(gpu_info_lock_);
    int flags = gpu_feature_type_;
    flags |= content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING |
             content::GPU_FEATURE_TYPE_WEBGL;
    gpu_feature_type_ = static_cast<GpuFeatureType>(flags);
  }

  EnableSoftwareRenderingIfNecessary();
  NotifyGpuInfoUpdate();
}

bool GpuDataManagerImpl::Merge(content::GPUInfo* object,
                               const content::GPUInfo& other) {
  if (object->device_id != other.device_id ||
      object->vendor_id != other.vendor_id) {
    *object = other;
    return true;
  }

  bool changed = false;
  if (!object->finalized) {
    object->finalized = other.finalized;
    object->initialization_time = other.initialization_time;
    object->optimus |= other.optimus;

    if (object->driver_vendor.empty()) {
      changed |= object->driver_vendor != other.driver_vendor;
      object->driver_vendor = other.driver_vendor;
    }
    if (object->driver_version.empty()) {
      changed |= object->driver_version != other.driver_version;
      object->driver_version = other.driver_version;
    }
    if (object->driver_date.empty()) {
      changed |= object->driver_date != other.driver_date;
      object->driver_date = other.driver_date;
    }
    if (object->pixel_shader_version.empty()) {
      changed |= object->pixel_shader_version != other.pixel_shader_version;
      object->pixel_shader_version = other.pixel_shader_version;
    }
    if (object->vertex_shader_version.empty()) {
      changed |= object->vertex_shader_version != other.vertex_shader_version;
      object->vertex_shader_version = other.vertex_shader_version;
    }
    if (object->gl_version.empty()) {
      changed |= object->gl_version != other.gl_version;
      object->gl_version = other.gl_version;
    }
    if (object->gl_version_string.empty()) {
      changed |= object->gl_version_string != other.gl_version_string;
      object->gl_version_string = other.gl_version_string;
    }
    if (object->gl_vendor.empty()) {
      changed |= object->gl_vendor != other.gl_vendor;
      object->gl_vendor = other.gl_vendor;
    }
    if (object->gl_renderer.empty()) {
      changed |= object->gl_renderer != other.gl_renderer;
      object->gl_renderer = other.gl_renderer;
    }
    if (object->gl_extensions.empty()) {
      changed |= object->gl_extensions != other.gl_extensions;
      object->gl_extensions = other.gl_extensions;
    }
    object->can_lose_context = other.can_lose_context;
    object->software_rendering = other.software_rendering;
#if defined(OS_WIN)
    if (object->dx_diagnostics.values.size() == 0 &&
        object->dx_diagnostics.children.size() == 0) {
      object->dx_diagnostics = other.dx_diagnostics;
      changed = true;
    }
#endif
  }
  return changed;
}
<commit_msg>Pass swiftshader-path flag down to GPU process<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"

#if defined(OS_MACOSX)
#include <CoreGraphics/CGDisplayConfiguration.h>
#endif

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/string_number_conversions.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/gfx/gl/gl_implementation.h"
#include "ui/gfx/gl/gl_switches.h"
#include "webkit/plugins/plugin_switches.h"

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

namespace {

#if defined(OS_MACOSX)
void DisplayReconfigCallback(CGDirectDisplayID display,
                             CGDisplayChangeSummaryFlags flags,
                             void* gpu_data_manager) {
  // TODO(zmo): this logging is temporary for crbug 88008 and will be removed.
  LOG(INFO) << "Display re-configuration: flags = 0x"
            << base::StringPrintf("%04x", flags);
  if (flags & kCGDisplayAddFlag) {
    GpuDataManagerImpl* manager =
        reinterpret_cast<GpuDataManagerImpl*>(gpu_data_manager);
    DCHECK(manager);
    manager->HandleGpuSwitch();
  }
}
#endif

}  // namespace anonymous

// 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 defined(OS_MACOSX)
  CGDisplayRegisterReconfigurationCallback(DisplayReconfigCallback, this);
#endif
}

GpuDataManagerImpl::~GpuDataManagerImpl() {
#if defined(OS_MACOSX)
  CGDisplayRemoveReconfigurationCallback(DisplayReconfigCallback, this);
#endif
}

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));

  complete_gpu_info_available_ =
      complete_gpu_info_available_ || gpu_info.finalized;
  complete_gpu_info_already_requested_ =
      complete_gpu_info_already_requested_ || gpu_info.finalized;
  {
    base::AutoLock auto_lock(gpu_info_lock_);
    if (!Merge(&gpu_info_, gpu_info))
      return;
    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;

  // 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);
  }
}

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

void GpuDataManagerImpl::HandleGpuSwitch() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  content::GPUInfo gpu_info;
  gpu_info_collector::CollectVideoCardInfo(&gpu_info);
  LOG(INFO) << "Switching to use GPU: vendor_id = 0x"
            << base::StringPrintf("%04x", gpu_info.vendor_id)
            << ", device_id = 0x"
            << base::StringPrintf("%04x", gpu_info.device_id);
  // TODO(zmo): update gpu_info_, re-run blacklist logic, maybe close and
  // relaunch GPU process.
}

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;

  {
    base::AutoLock auto_lock(gpu_info_lock_);
    int flags = gpu_feature_type_;
    flags |= content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING |
             content::GPU_FEATURE_TYPE_WEBGL;
    gpu_feature_type_ = static_cast<GpuFeatureType>(flags);
  }

  EnableSoftwareRenderingIfNecessary();
  NotifyGpuInfoUpdate();
}

bool GpuDataManagerImpl::Merge(content::GPUInfo* object,
                               const content::GPUInfo& other) {
  if (object->device_id != other.device_id ||
      object->vendor_id != other.vendor_id) {
    *object = other;
    return true;
  }

  bool changed = false;
  if (!object->finalized) {
    object->finalized = other.finalized;
    object->initialization_time = other.initialization_time;
    object->optimus |= other.optimus;

    if (object->driver_vendor.empty()) {
      changed |= object->driver_vendor != other.driver_vendor;
      object->driver_vendor = other.driver_vendor;
    }
    if (object->driver_version.empty()) {
      changed |= object->driver_version != other.driver_version;
      object->driver_version = other.driver_version;
    }
    if (object->driver_date.empty()) {
      changed |= object->driver_date != other.driver_date;
      object->driver_date = other.driver_date;
    }
    if (object->pixel_shader_version.empty()) {
      changed |= object->pixel_shader_version != other.pixel_shader_version;
      object->pixel_shader_version = other.pixel_shader_version;
    }
    if (object->vertex_shader_version.empty()) {
      changed |= object->vertex_shader_version != other.vertex_shader_version;
      object->vertex_shader_version = other.vertex_shader_version;
    }
    if (object->gl_version.empty()) {
      changed |= object->gl_version != other.gl_version;
      object->gl_version = other.gl_version;
    }
    if (object->gl_version_string.empty()) {
      changed |= object->gl_version_string != other.gl_version_string;
      object->gl_version_string = other.gl_version_string;
    }
    if (object->gl_vendor.empty()) {
      changed |= object->gl_vendor != other.gl_vendor;
      object->gl_vendor = other.gl_vendor;
    }
    if (object->gl_renderer.empty()) {
      changed |= object->gl_renderer != other.gl_renderer;
      object->gl_renderer = other.gl_renderer;
    }
    if (object->gl_extensions.empty()) {
      changed |= object->gl_extensions != other.gl_extensions;
      object->gl_extensions = other.gl_extensions;
    }
    object->can_lose_context = other.can_lose_context;
    object->software_rendering = other.software_rendering;
#if defined(OS_WIN)
    if (object->dx_diagnostics.values.size() == 0 &&
        object->dx_diagnostics.children.size() == 0) {
      object->dx_diagnostics = other.dx_diagnostics;
      changed = true;
    }
#endif
  }
  return changed;
}
<|endoftext|>


<commit_before>#pragma once
/**
	@file
	@brief definition of Op
	@author MITSUNARI Shigeo(@herumi)
	@license modified new BSD license
	http://opensource.org/licenses/BSD-3-Clause
*/
#include <mcl/gmp_util.hpp>
#include <memory.h>
#include <mcl/array.hpp>

#if defined(__EMSCRIPTEN__) || defined(__wasm__)
	#define MCL_DONT_USE_XBYAK
	#define MCL_DONT_USE_OPENSSL
#endif
#if !defined(MCL_DONT_USE_XBYAK) && (defined(_WIN64) || defined(__x86_64__)) && (MCL_SIZEOF_UNIT == 8)
	#define MCL_USE_XBYAK
	#define MCL_XBYAK_DIRECT_CALL
#endif

#define MCL_MAX_HASH_BIT_SIZE 512

namespace mcl {

static const int version = 0x096; /* 0xABC = A.BC */

/*
	specifies available string format mode for X::setIoMode()
	// for Fp, Fp2, Fp6, Fp12
	default(0) : IoDec
	printable string(zero terminated, variable size)
	IoBin(2) | IoDec(10) | IoHex(16) | IoBinPrefix | IoHexPrefix

	byte string(not zero terminated, fixed size)
	IoArray | IoArrayRaw
	IoArray = IoSerialize

	// for Ec
	affine(0) | IoEcCompY | IoComp
	default : affine

	affine and IoEcCompY are available with ioMode for Fp
	IoSerialize ignores ioMode for Fp

	IoAuto
		dec or hex according to ios_base::fmtflags
	IoBin
		binary number([01]+)
	IoDec
		decimal number
	IoHex
		hexadecimal number([0-9a-fA-F]+)
	IoBinPrefix
		0b + <binary number>
	IoHexPrefix
		0x + <hexadecimal number>
	IoArray
		array of Unit(fixed size = Fp::getByteSize())
	IoArrayRaw
		array of Unit(fixed size = Fp::getByteSize()) without Montgomery conversion

	// for Ec::setIoMode()
	IoEcAffine(default)
	"0" ; infinity
	"1 <x> <y>" ; affine coordinate

	IoEcProj
	"4" <x> <y> <z> ; projective or jacobi coordinate

	IoEcCompY
		1-bit y prepresentation of elliptic curve
		"2 <x>" ; compressed for even y
		"3 <x>" ; compressed for odd y

	IoSerialize
		if isMSBserialize(): // p is not full bit
			size = Fp::getByteSize()
			use MSB of array of x for 1-bit y for prime p where (p % 8 != 0)
			[0] ; infinity
			<x> ; for even y
			<x>|1 ; for odd y ; |1 means set MSB of x
		else:
			size = Fp::getByteSize() + 1
			[0] ; infinity
			2 <x> ; for even y
			3 <x> ; for odd y
*/
enum IoMode {
	IoAuto = 0, // dec or hex according to ios_base::fmtflags
	IoBin = 2, // binary number without prefix
	IoDec = 10, // decimal number without prefix
	IoHex = 16, // hexadecimal number without prefix
	IoArray = 32, // array of Unit(fixed size)
	IoArrayRaw = 64, // raw array of Unit without Montgomery conversion
	IoPrefix = 128, // append '0b'(bin) or '0x'(hex)
	IoBinPrefix = IoBin | IoPrefix,
	IoHexPrefix = IoHex | IoPrefix,
	IoEcAffine = 0, // affine coordinate
	IoEcCompY = 256, // 1-bit y representation of elliptic curve
	IoSerialize = 512, // use MBS for 1-bit y
	IoFixedSizeByteSeq = IoSerialize, // obsolete
	IoEcProj = 1024, // projective or jacobi coordinate
	IoSerializeHexStr = 2048 // printable hex string
};

namespace fp {

const size_t UnitBitSize = sizeof(Unit) * 8;

const size_t maxUnitSize = (MCL_MAX_BIT_SIZE + UnitBitSize - 1) / UnitBitSize;
#define MCL_MAX_UNIT_SIZE ((MCL_MAX_BIT_SIZE + MCL_UNIT_BIT_SIZE - 1) / MCL_UNIT_BIT_SIZE)

struct FpGenerator;
struct Op;

typedef void (*void1u)(Unit*);
typedef void (*void2u)(Unit*, const Unit*);
typedef void (*void2uI)(Unit*, const Unit*, Unit);
typedef void (*void2uIu)(Unit*, const Unit*, Unit, const Unit*);
typedef void (*void2uOp)(Unit*, const Unit*, const Op&);
typedef void (*void3u)(Unit*, const Unit*, const Unit*);
typedef void (*void4u)(Unit*, const Unit*, const Unit*, const Unit*);
typedef int (*int2u)(Unit*, const Unit*);

typedef Unit (*u1uII)(Unit*, Unit, Unit);
typedef Unit (*u3u)(Unit*, const Unit*, const Unit*);

/*
	disable -Wcast-function-type
	the number of arguments of some JIT functions is smaller than that of T
*/
template<class T, class S>
T func_ptr_cast(S func)
{
	return reinterpret_cast<T>(reinterpret_cast<void*>(func));
}
struct Block {
	const Unit *p; // pointer to original FpT.v_
	size_t n;
	Unit v_[maxUnitSize];
};

enum Mode {
	FP_AUTO,
	FP_GMP,
	FP_GMP_MONT,
	FP_LLVM,
	FP_LLVM_MONT,
	FP_XBYAK
};

enum PrimeMode {
	PM_GENERIC = 0,
	PM_NIST_P192,
	PM_SECP256K1,
	PM_NIST_P521
};

enum MaskMode {
	NoMask = 0, // throw if greater or equal
	SmallMask = 1, // 1-bit smaller mask if greater or equal
	MaskAndMod = 2, // mask and substract if greater or equal
	Mod = 3 // mod p
};

struct Op {
	/*
		don't change the layout of rp and p
		asm code assumes &rp + 1 == p
	*/
	Unit rp;
	Unit p[maxUnitSize];
	mpz_class mp;
	uint32_t pmod4;
	mcl::SquareRoot sq;
	mcl::Modp modp;
	Unit half[maxUnitSize]; // (p + 1) / 2
	Unit oneRep[maxUnitSize]; // 1(=inv R if Montgomery)
	/*
		for Montgomery
		one = 1
		R = (1 << (N * sizeof(Unit) * 8)) % p
		R2 = (R * R) % p
		R3 = RR^3
	*/
	Unit one[maxUnitSize];
	Unit R2[maxUnitSize];
	Unit R3[maxUnitSize];
#ifdef MCL_USE_XBYAK
	FpGenerator *fg;
	mcl::Array<Unit> invTbl;
#endif
	void3u fp_addA_;
	void3u fp_subA_;
	void2u fp_negA_;
	void3u fp_mulA_;
	void2u fp_sqrA_;
	void3u fp2_addA_;
	void3u fp2_subA_;
	void2u fp2_negA_;
	void3u fp2_mulA_;
	void2u fp2_sqrA_;
	void3u fpDbl_addA_;
	void3u fpDbl_subA_;
	void3u fpDbl_mulPreA_;
	void2u fpDbl_sqrPreA_;
	void2u fpDbl_modA_;
	void3u fp2Dbl_mulPreA_;
	void2u fp2Dbl_sqrPreA_;
	size_t maxN;
	size_t N;
	size_t bitSize;
	bool (*fp_isZero)(const Unit*);
	void1u fp_clear;
	void2u fp_copy;
	void2u fp_shr1;
	void3u fp_neg;
	void4u fp_add;
	void4u fp_sub;
	void4u fp_mul;
	void3u fp_sqr;
	void2uOp fp_invOp;
	void2uIu fp_mulUnit; // fpN1_mod + fp_mulUnitPre

	void3u fpDbl_mulPre;
	void2u fpDbl_sqrPre;
	int2u fp_preInv;
	void2uI fp_mulUnitPre; // z[N + 1] = x[N] * y
	void3u fpN1_mod; // y[N] = x[N + 1] % p[N]

	void4u fpDbl_add;
	void4u fpDbl_sub;
	void3u fpDbl_mod;

	u3u fp_addPre; // without modulo p
	u3u fp_subPre; // without modulo p
	u3u fpDbl_addPre;
	u3u fpDbl_subPre;
	/*
		for Fp2 = F[u] / (u^2 + 1)
		x = a + bu
	*/
	int xi_a; // xi = xi_a + u
	void4u fp2_mulNF;
	void2u fp2_inv;
	void2u fp2_mul_xiA_;
	uint32_t (*hash)(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize);

	PrimeMode primeMode;
	bool isFullBit; // true if bitSize % uniSize == 0
	bool isMont; // true if use Montgomery
	bool isFastMod; // true if modulo is fast

	Op()
	{
		clear();
	}
	~Op()
	{
#ifdef MCL_USE_XBYAK
		destroyFpGenerator(fg);
#endif
	}
	void clear()
	{
		rp = 0;
		memset(p, 0, sizeof(p));
		mp = 0;
		pmod4 = 0;
		sq.clear();
		// fg is not set
		memset(half, 0, sizeof(half));
		memset(oneRep, 0, sizeof(oneRep));
		memset(one, 0, sizeof(one));
		memset(R2, 0, sizeof(R2));
		memset(R3, 0, sizeof(R3));
#ifdef MCL_USE_XBYAK
		invTbl.clear();
#endif
		fp_addA_ = 0;
		fp_subA_ = 0;
		fp_negA_ = 0;
		fp_mulA_ = 0;
		fp_sqrA_ = 0;
		fp2_addA_ = 0;
		fp2_subA_ = 0;
		fp2_negA_ = 0;
		fp2_mulA_ = 0;
		fp2_sqrA_ = 0;
		fpDbl_addA_ = 0;
		fpDbl_subA_ = 0;
		fpDbl_mulPreA_ = 0;
		fpDbl_sqrPreA_ = 0;
		fpDbl_modA_ = 0;
		fp2Dbl_mulPreA_ = 0;
		fp2Dbl_sqrPreA_ = 0;
		maxN = 0;
		N = 0;
		bitSize = 0;
		fp_isZero = 0;
		fp_clear = 0;
		fp_copy = 0;
		fp_shr1 = 0;
		fp_neg = 0;
		fp_add = 0;
		fp_sub = 0;
		fp_mul = 0;
		fp_sqr = 0;
		fp_invOp = 0;
		fp_mulUnit = 0;

		fpDbl_mulPre = 0;
		fpDbl_sqrPre = 0;
		fp_preInv = 0;
		fp_mulUnitPre = 0;
		fpN1_mod = 0;

		fpDbl_add = 0;
		fpDbl_sub = 0;
		fpDbl_mod = 0;

		fp_addPre = 0;
		fp_subPre = 0;
		fpDbl_addPre = 0;
		fpDbl_subPre = 0;

		xi_a = 0;
		fp2_mulNF = 0;
		fp2_inv = 0;
		fp2_mul_xiA_ = 0;
		hash = 0;

		primeMode = PM_GENERIC;
		isFullBit = false;
		isMont = false;
		isFastMod = false;
	}
	void fromMont(Unit* y, const Unit *x) const
	{
		/*
			M(x, y) = xyR^-1
			y = M(x, 1) = xR^-1
		*/
		fp_mul(y, x, one, p);
	}
	void toMont(Unit* y, const Unit *x) const
	{
		/*
			y = M(x, R2) = xR^2 R^-1 = xR
		*/
		fp_mul(y, x, R2, p);
	}
	bool init(const mpz_class& p, size_t maxBitSize, int xi_a, Mode mode, size_t mclMaxBitSize = MCL_MAX_BIT_SIZE);
#ifdef MCL_USE_XBYAK
	static FpGenerator* createFpGenerator();
	static void destroyFpGenerator(FpGenerator *fg);
#endif
private:
	Op(const Op&);
	void operator=(const Op&);
};

inline const char* getIoSeparator(int ioMode)
{
	return (ioMode & (IoArray | IoArrayRaw | IoSerialize | IoSerializeHexStr)) ? "" : " ";
}

inline void dump(const char *s, size_t n)
{
	for (size_t i = 0; i < n; i++) {
		printf("%02x ", (uint8_t)s[i]);
	}
	printf("\n");
}

#ifndef CYBOZU_DONT_USE_STRING
int detectIoMode(int ioMode, const std::ios_base& ios);

inline void dump(const std::string& s)
{
	dump(s.c_str(), s.size());
}
#endif

} } // mcl::fp
<commit_msg>dump() accepts const void*<commit_after>#pragma once
/**
	@file
	@brief definition of Op
	@author MITSUNARI Shigeo(@herumi)
	@license modified new BSD license
	http://opensource.org/licenses/BSD-3-Clause
*/
#include <mcl/gmp_util.hpp>
#include <memory.h>
#include <mcl/array.hpp>

#if defined(__EMSCRIPTEN__) || defined(__wasm__)
	#define MCL_DONT_USE_XBYAK
	#define MCL_DONT_USE_OPENSSL
#endif
#if !defined(MCL_DONT_USE_XBYAK) && (defined(_WIN64) || defined(__x86_64__)) && (MCL_SIZEOF_UNIT == 8)
	#define MCL_USE_XBYAK
	#define MCL_XBYAK_DIRECT_CALL
#endif

#define MCL_MAX_HASH_BIT_SIZE 512

namespace mcl {

static const int version = 0x096; /* 0xABC = A.BC */

/*
	specifies available string format mode for X::setIoMode()
	// for Fp, Fp2, Fp6, Fp12
	default(0) : IoDec
	printable string(zero terminated, variable size)
	IoBin(2) | IoDec(10) | IoHex(16) | IoBinPrefix | IoHexPrefix

	byte string(not zero terminated, fixed size)
	IoArray | IoArrayRaw
	IoArray = IoSerialize

	// for Ec
	affine(0) | IoEcCompY | IoComp
	default : affine

	affine and IoEcCompY are available with ioMode for Fp
	IoSerialize ignores ioMode for Fp

	IoAuto
		dec or hex according to ios_base::fmtflags
	IoBin
		binary number([01]+)
	IoDec
		decimal number
	IoHex
		hexadecimal number([0-9a-fA-F]+)
	IoBinPrefix
		0b + <binary number>
	IoHexPrefix
		0x + <hexadecimal number>
	IoArray
		array of Unit(fixed size = Fp::getByteSize())
	IoArrayRaw
		array of Unit(fixed size = Fp::getByteSize()) without Montgomery conversion

	// for Ec::setIoMode()
	IoEcAffine(default)
	"0" ; infinity
	"1 <x> <y>" ; affine coordinate

	IoEcProj
	"4" <x> <y> <z> ; projective or jacobi coordinate

	IoEcCompY
		1-bit y prepresentation of elliptic curve
		"2 <x>" ; compressed for even y
		"3 <x>" ; compressed for odd y

	IoSerialize
		if isMSBserialize(): // p is not full bit
			size = Fp::getByteSize()
			use MSB of array of x for 1-bit y for prime p where (p % 8 != 0)
			[0] ; infinity
			<x> ; for even y
			<x>|1 ; for odd y ; |1 means set MSB of x
		else:
			size = Fp::getByteSize() + 1
			[0] ; infinity
			2 <x> ; for even y
			3 <x> ; for odd y
*/
enum IoMode {
	IoAuto = 0, // dec or hex according to ios_base::fmtflags
	IoBin = 2, // binary number without prefix
	IoDec = 10, // decimal number without prefix
	IoHex = 16, // hexadecimal number without prefix
	IoArray = 32, // array of Unit(fixed size)
	IoArrayRaw = 64, // raw array of Unit without Montgomery conversion
	IoPrefix = 128, // append '0b'(bin) or '0x'(hex)
	IoBinPrefix = IoBin | IoPrefix,
	IoHexPrefix = IoHex | IoPrefix,
	IoEcAffine = 0, // affine coordinate
	IoEcCompY = 256, // 1-bit y representation of elliptic curve
	IoSerialize = 512, // use MBS for 1-bit y
	IoFixedSizeByteSeq = IoSerialize, // obsolete
	IoEcProj = 1024, // projective or jacobi coordinate
	IoSerializeHexStr = 2048 // printable hex string
};

namespace fp {

const size_t UnitBitSize = sizeof(Unit) * 8;

const size_t maxUnitSize = (MCL_MAX_BIT_SIZE + UnitBitSize - 1) / UnitBitSize;
#define MCL_MAX_UNIT_SIZE ((MCL_MAX_BIT_SIZE + MCL_UNIT_BIT_SIZE - 1) / MCL_UNIT_BIT_SIZE)

struct FpGenerator;
struct Op;

typedef void (*void1u)(Unit*);
typedef void (*void2u)(Unit*, const Unit*);
typedef void (*void2uI)(Unit*, const Unit*, Unit);
typedef void (*void2uIu)(Unit*, const Unit*, Unit, const Unit*);
typedef void (*void2uOp)(Unit*, const Unit*, const Op&);
typedef void (*void3u)(Unit*, const Unit*, const Unit*);
typedef void (*void4u)(Unit*, const Unit*, const Unit*, const Unit*);
typedef int (*int2u)(Unit*, const Unit*);

typedef Unit (*u1uII)(Unit*, Unit, Unit);
typedef Unit (*u3u)(Unit*, const Unit*, const Unit*);

/*
	disable -Wcast-function-type
	the number of arguments of some JIT functions is smaller than that of T
*/
template<class T, class S>
T func_ptr_cast(S func)
{
	return reinterpret_cast<T>(reinterpret_cast<void*>(func));
}
struct Block {
	const Unit *p; // pointer to original FpT.v_
	size_t n;
	Unit v_[maxUnitSize];
};

enum Mode {
	FP_AUTO,
	FP_GMP,
	FP_GMP_MONT,
	FP_LLVM,
	FP_LLVM_MONT,
	FP_XBYAK
};

enum PrimeMode {
	PM_GENERIC = 0,
	PM_NIST_P192,
	PM_SECP256K1,
	PM_NIST_P521
};

enum MaskMode {
	NoMask = 0, // throw if greater or equal
	SmallMask = 1, // 1-bit smaller mask if greater or equal
	MaskAndMod = 2, // mask and substract if greater or equal
	Mod = 3 // mod p
};

struct Op {
	/*
		don't change the layout of rp and p
		asm code assumes &rp + 1 == p
	*/
	Unit rp;
	Unit p[maxUnitSize];
	mpz_class mp;
	uint32_t pmod4;
	mcl::SquareRoot sq;
	mcl::Modp modp;
	Unit half[maxUnitSize]; // (p + 1) / 2
	Unit oneRep[maxUnitSize]; // 1(=inv R if Montgomery)
	/*
		for Montgomery
		one = 1
		R = (1 << (N * sizeof(Unit) * 8)) % p
		R2 = (R * R) % p
		R3 = RR^3
	*/
	Unit one[maxUnitSize];
	Unit R2[maxUnitSize];
	Unit R3[maxUnitSize];
#ifdef MCL_USE_XBYAK
	FpGenerator *fg;
	mcl::Array<Unit> invTbl;
#endif
	void3u fp_addA_;
	void3u fp_subA_;
	void2u fp_negA_;
	void3u fp_mulA_;
	void2u fp_sqrA_;
	void3u fp2_addA_;
	void3u fp2_subA_;
	void2u fp2_negA_;
	void3u fp2_mulA_;
	void2u fp2_sqrA_;
	void3u fpDbl_addA_;
	void3u fpDbl_subA_;
	void3u fpDbl_mulPreA_;
	void2u fpDbl_sqrPreA_;
	void2u fpDbl_modA_;
	void3u fp2Dbl_mulPreA_;
	void2u fp2Dbl_sqrPreA_;
	size_t maxN;
	size_t N;
	size_t bitSize;
	bool (*fp_isZero)(const Unit*);
	void1u fp_clear;
	void2u fp_copy;
	void2u fp_shr1;
	void3u fp_neg;
	void4u fp_add;
	void4u fp_sub;
	void4u fp_mul;
	void3u fp_sqr;
	void2uOp fp_invOp;
	void2uIu fp_mulUnit; // fpN1_mod + fp_mulUnitPre

	void3u fpDbl_mulPre;
	void2u fpDbl_sqrPre;
	int2u fp_preInv;
	void2uI fp_mulUnitPre; // z[N + 1] = x[N] * y
	void3u fpN1_mod; // y[N] = x[N + 1] % p[N]

	void4u fpDbl_add;
	void4u fpDbl_sub;
	void3u fpDbl_mod;

	u3u fp_addPre; // without modulo p
	u3u fp_subPre; // without modulo p
	u3u fpDbl_addPre;
	u3u fpDbl_subPre;
	/*
		for Fp2 = F[u] / (u^2 + 1)
		x = a + bu
	*/
	int xi_a; // xi = xi_a + u
	void4u fp2_mulNF;
	void2u fp2_inv;
	void2u fp2_mul_xiA_;
	uint32_t (*hash)(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize);

	PrimeMode primeMode;
	bool isFullBit; // true if bitSize % uniSize == 0
	bool isMont; // true if use Montgomery
	bool isFastMod; // true if modulo is fast

	Op()
	{
		clear();
	}
	~Op()
	{
#ifdef MCL_USE_XBYAK
		destroyFpGenerator(fg);
#endif
	}
	void clear()
	{
		rp = 0;
		memset(p, 0, sizeof(p));
		mp = 0;
		pmod4 = 0;
		sq.clear();
		// fg is not set
		memset(half, 0, sizeof(half));
		memset(oneRep, 0, sizeof(oneRep));
		memset(one, 0, sizeof(one));
		memset(R2, 0, sizeof(R2));
		memset(R3, 0, sizeof(R3));
#ifdef MCL_USE_XBYAK
		invTbl.clear();
#endif
		fp_addA_ = 0;
		fp_subA_ = 0;
		fp_negA_ = 0;
		fp_mulA_ = 0;
		fp_sqrA_ = 0;
		fp2_addA_ = 0;
		fp2_subA_ = 0;
		fp2_negA_ = 0;
		fp2_mulA_ = 0;
		fp2_sqrA_ = 0;
		fpDbl_addA_ = 0;
		fpDbl_subA_ = 0;
		fpDbl_mulPreA_ = 0;
		fpDbl_sqrPreA_ = 0;
		fpDbl_modA_ = 0;
		fp2Dbl_mulPreA_ = 0;
		fp2Dbl_sqrPreA_ = 0;
		maxN = 0;
		N = 0;
		bitSize = 0;
		fp_isZero = 0;
		fp_clear = 0;
		fp_copy = 0;
		fp_shr1 = 0;
		fp_neg = 0;
		fp_add = 0;
		fp_sub = 0;
		fp_mul = 0;
		fp_sqr = 0;
		fp_invOp = 0;
		fp_mulUnit = 0;

		fpDbl_mulPre = 0;
		fpDbl_sqrPre = 0;
		fp_preInv = 0;
		fp_mulUnitPre = 0;
		fpN1_mod = 0;

		fpDbl_add = 0;
		fpDbl_sub = 0;
		fpDbl_mod = 0;

		fp_addPre = 0;
		fp_subPre = 0;
		fpDbl_addPre = 0;
		fpDbl_subPre = 0;

		xi_a = 0;
		fp2_mulNF = 0;
		fp2_inv = 0;
		fp2_mul_xiA_ = 0;
		hash = 0;

		primeMode = PM_GENERIC;
		isFullBit = false;
		isMont = false;
		isFastMod = false;
	}
	void fromMont(Unit* y, const Unit *x) const
	{
		/*
			M(x, y) = xyR^-1
			y = M(x, 1) = xR^-1
		*/
		fp_mul(y, x, one, p);
	}
	void toMont(Unit* y, const Unit *x) const
	{
		/*
			y = M(x, R2) = xR^2 R^-1 = xR
		*/
		fp_mul(y, x, R2, p);
	}
	bool init(const mpz_class& p, size_t maxBitSize, int xi_a, Mode mode, size_t mclMaxBitSize = MCL_MAX_BIT_SIZE);
#ifdef MCL_USE_XBYAK
	static FpGenerator* createFpGenerator();
	static void destroyFpGenerator(FpGenerator *fg);
#endif
private:
	Op(const Op&);
	void operator=(const Op&);
};

inline const char* getIoSeparator(int ioMode)
{
	return (ioMode & (IoArray | IoArrayRaw | IoSerialize | IoSerializeHexStr)) ? "" : " ";
}

inline void dump(const void *buf, size_t n)
{
	const uint8_t *s = (const uint8_t *)buf;
	for (size_t i = 0; i < n; i++) {
		printf("%02x ", s[i]);
	}
	printf("\n");
}

#ifndef CYBOZU_DONT_USE_STRING
int detectIoMode(int ioMode, const std::ios_base& ios);

inline void dump(const std::string& s)
{
	dump(s.c_str(), s.size());
}
#endif

} } // mcl::fp
<|endoftext|>


<commit_before>#include "style.h"
#include "platform.h"
#include "util/geometryHandler.h"
#include "util/jsonExtractor.h"

/*
 * Style Class Methods
 */

Style::Style(std::string _geomType, std::string _styleName, GLenum _drawMode) : m_geomType(_geomType), m_styleName(_styleName), m_drawMode(_drawMode) {
}

void Style::setFragShaderSrc(std::string _fragShaderSrcStr) {
    m_fragShaderSrcStr = std::move(_fragShaderSrcStr);
}

void Style::setVertShaderSrc(std::string _vertShaderSrcStr) {
    m_vertShaderSrcStr = std::move(_vertShaderSrcStr);
}

void Style::updateLayers(std::vector<std::pair<std::string, GLuint>> _newLayers) {
    for(auto& newLayer : _newLayers) {
        if(m_layerColorMap.find(newLayer.first) == m_layerColorMap.end()) {
            m_layerColorMap.emplace(std::make_pair(newLayer.first, newLayer.second));
        }
        else {
            m_layerColorMap[newLayer.first] = newLayer.second;
        }
    }
}

/*
 * Polygon Style Class Methods
 */

PolygonStyle::PolygonStyle(std::string _geomType, std::string _styleName, GLenum _drawMode) : Style(_geomType, _styleName, _drawMode) {

    // Pass in a fileName or a url to construct shader strings from
    m_vertShaderSrcStr =
        "#ifdef GL_ES\n"
        "precision mediump float;\n"
        "#endif\n"
        "uniform mat4 u_modelViewProj;\n"
        "attribute vec4 a_position;\n"
        "attribute vec4 a_color;\n"
        "varying vec4 v_color;\n"
        "void main() {\n"
        "  v_color = a_color;\n"
        "  gl_Position = u_modelViewProj * a_position;\n"
        "}\n";

    m_fragShaderSrcStr =
        "#ifdef GL_ES\n"
        "precision mediump float;\n"
        "#endif\n"
        "varying vec4 v_color;\n"
        "void main(void) {\n"
        "  gl_FragColor = v_color;\n"
        "}\n";

    constructVertexLayout();
    constructShaderProgram();
}

PolygonStyle::PolygonStyle(std::string _geomType, GLenum _drawMode) : PolygonStyle(_geomType, _geomType, _drawMode) {}

void PolygonStyle::constructVertexLayout() {
    // fixed per style... this is basic position, normal color
    m_vertexLayout = std::shared_ptr<VertexLayout>(new VertexLayout({
        {"a_position", 3, GL_FLOAT, false, 0},
        {"a_normal", 3, GL_FLOAT, false, 0},
        {"a_color", 4, GL_UNSIGNED_BYTE, true, 0}
    }));
}

void PolygonStyle::constructShaderProgram() {
    m_shaderProgram = std::shared_ptr<ShaderProgram>(new ShaderProgram());
    m_shaderProgram->buildFromSourceStrings(m_fragShaderSrcStr, m_vertShaderSrcStr);
}

void PolygonStyle::addData(const Json::Value& _jsonRoot, MapTile& _tile, const MapProjection& _mapProjection) {
    // Create a vboMesh which will eventually contain all the data
    std::unique_ptr<VboMesh> mesh(new VboMesh(m_vertexLayout, m_drawMode));

    //Extract Feature Properties
    for(auto& layer : m_layerColorMap) {
        Json::Value layerFeatures = _jsonRoot[layer.first.c_str()]["features"];
        //iterate through all features and check for respective geometry type
        for(int i = 0; i < layerFeatures.size(); i++) {
            if(m_geomType.compare(JsonExtractor::extractGeomType(layerFeatures[i])) == 0) {
                std::vector<glm::vec3> extractedGeomCoords;
                std::vector<int> polyRingSizes;
                JsonExtractor::extractGeomCoords(extractedGeomCoords, polyRingSizes, layerFeatures[i], _tile.getOrigin(), _mapProjection);
                GeometryHandler::buildPolygon(extractedGeomCoords, polyRingSizes, m_vertCoords, m_vertNormals, m_indices);
                //GeometryHandler::buildPolygonExtrusion(JsonExtractor::extractGeomCoords(layerFeatures, _tile.getOrigin(), _mapProjection), m_vertCoords, m_vertNormals, m_indices);
                /* fill style's m_vertices with vertCoord, vertNormal and color data */
                fillVertexData(layer.second);
            }
            else {
                continue;
            }
        }
    }
    if(m_vertices.size() == 0) {
        //Nothing to add to mesh, get rid of mesh
        mesh.reset(nullptr);
    }
    else {
        //Add vertices to mesh
        mesh->addVertices((GLbyte*)m_vertices.data(), (int)m_vertices.size());
        mesh->addIndices(m_indices.data(), (int)m_indices.size());
        //1. addGeometry should take either take the name of the style or pointer to the style (this)
        _tile.addGeometry(*this, std::move(mesh));
    }
}

void PolygonStyle::fillVertexData(const GLuint& _abgr) {
    for(int i = (int)m_vertices.size(); i < m_vertCoords.size(); i++) {
        m_vertices.push_back( { m_vertCoords[i].x, m_vertCoords[i].y, m_vertCoords[i].z,
                                m_vertNormals[i].x, m_vertNormals[i].y, m_vertNormals[i].z,
                                _abgr
                              });
    }
    return;
}

void PolygonStyle::clearStyleData() {
    m_vertices.clear();
    m_indices.clear();
    m_vertCoords.clear();
    m_vertNormals.clear();
}

void PolygonStyle::setup() {
}

/*
 * MultiPolygon Style Class Methods
 */

MultiPolygonStyle::MultiPolygonStyle(std::string _geomType, std::string _styleName, GLenum _drawMode) : Style(_geomType, _styleName, _drawMode) {

    // Pass in a fileName or a url to construct shader strings from
    m_vertShaderSrcStr =
        "#ifdef GL_ES\n"
        "precision mediump float;\n"
        "#endif\n"
        "uniform mat4 u_modelViewProj;\n"
        "attribute vec4 a_position;\n"
        "attribute vec4 a_color;\n"
        "varying vec4 v_color;\n"
        "void main() {\n"
        "  v_color = a_color;\n"
        "  gl_Position = u_modelViewProj * a_position;\n"
        "}\n";

    m_fragShaderSrcStr =
        "#ifdef GL_ES\n"
        "precision mediump float;\n"
        "#endif\n"
        "varying vec4 v_color;\n"
        "void main(void) {\n"
        "  gl_FragColor = v_color;\n"
        "}\n";

    constructVertexLayout();
    constructShaderProgram();
}

MultiPolygonStyle::MultiPolygonStyle(std::string _geomType, GLenum _drawMode) : MultiPolygonStyle(_geomType, _geomType, _drawMode) {}

void MultiPolygonStyle::constructVertexLayout() {
    // fixed per style... this is basic position, normal color
    m_vertexLayout = std::shared_ptr<VertexLayout>(new VertexLayout({
        {"a_position", 3, GL_FLOAT, false, 0},
        {"a_normal", 3, GL_FLOAT, false, 0},
        {"a_color", 4, GL_UNSIGNED_BYTE, true, 0}
    }));
}

void MultiPolygonStyle::constructShaderProgram() {
    m_shaderProgram = std::shared_ptr<ShaderProgram>(new ShaderProgram());
    m_shaderProgram->buildFromSourceStrings(m_fragShaderSrcStr, m_vertShaderSrcStr);
}

void MultiPolygonStyle::addData(const Json::Value& _jsonRoot, MapTile& _tile, const MapProjection& _mapProjection) {
    // Create a vboMesh which will eventually contain all the data
    std::unique_ptr<VboMesh> mesh(new VboMesh(m_vertexLayout, m_drawMode));

    //Extract Feature Properties
    for(auto& layer : m_layerColorMap) {
        Json::Value layerFeatures = _jsonRoot[layer.first.c_str()]["features"];
        //iterate through all features and check for respective geometry type
        for(int i = 0; i < layerFeatures.size(); i++) {
            if(m_geomType.compare(JsonExtractor::extractGeomType(layerFeatures[i])) == 0) {
                int numPolys = JsonExtractor::extractNumPoly(layerFeatures[i]);
                std::vector<glm::vec3> extractedGeomCoords;
                std::vector<int> polyRingSizes;
                JsonExtractor::extractGeomCoords(extractedGeomCoords, polyRingSizes, layerFeatures[i], _tile.getOrigin(), _mapProjection, numPolys);
                GeometryHandler::buildPolygon(extractedGeomCoords, polyRingSizes, m_vertCoords, m_vertNormals, m_indices);
                //GeometryHandler::buildPolygonExtrusion(JsonExtractor::extractGeomCoords(layerFeatures, _tile.getOrigin(), _mapProjection), m_vertCoords, m_vertNormals, m_indices);
                /* fill style's m_vertices with vertCoord, vertNormal and color data */
                fillVertexData(layer.second);
            }
            else {
                continue;
            }
        }
    }
    if(m_vertices.size() == 0) {
        //Nothing to add to mesh, get rid of mesh
        mesh.reset(nullptr);
    }
    else {
        //Add vertices to mesh
        mesh->addVertices((GLbyte*)m_vertices.data(), m_vertices.size());
        mesh->addIndices((GLushort*)m_indices.data(), m_indices.size());
        //1. addGeometry should take either take the name of the style or pointer to the style (this)
        _tile.addGeometry(*this, std::move(mesh));
    }
}

void MultiPolygonStyle::fillVertexData(const GLuint& _abgr) {
    for(int i = m_vertices.size(); i < m_vertCoords.size(); i++) {
        m_vertices.push_back( { m_vertCoords[i].x, m_vertCoords[i].y, m_vertCoords[i].z,
                                m_vertNormals[i].x, m_vertNormals[i].y, m_vertNormals[i].z,
                                _abgr
                              });
    }
    return;
}

void MultiPolygonStyle::clearStyleData() {
    m_vertices.clear();
    m_indices.clear();
    m_vertCoords.clear();
    m_vertNormals.clear();
}

void MultiPolygonStyle::setup() {
}
<commit_msg>added calls to geometry extrusion<commit_after>#include "style.h"
#include "platform.h"
#include "util/geometryHandler.h"
#include "util/jsonExtractor.h"

/*
 * Style Class Methods
 */

Style::Style(std::string _geomType, std::string _styleName, GLenum _drawMode) : m_geomType(_geomType), m_styleName(_styleName), m_drawMode(_drawMode) {
}

void Style::setFragShaderSrc(std::string _fragShaderSrcStr) {
    m_fragShaderSrcStr = std::move(_fragShaderSrcStr);
}

void Style::setVertShaderSrc(std::string _vertShaderSrcStr) {
    m_vertShaderSrcStr = std::move(_vertShaderSrcStr);
}

void Style::updateLayers(std::vector<std::pair<std::string, GLuint>> _newLayers) {
    for(auto& newLayer : _newLayers) {
        if(m_layerColorMap.find(newLayer.first) == m_layerColorMap.end()) {
            m_layerColorMap.emplace(std::make_pair(newLayer.first, newLayer.second));
        }
        else {
            m_layerColorMap[newLayer.first] = newLayer.second;
        }
    }
}

/*
 * Polygon Style Class Methods
 */

PolygonStyle::PolygonStyle(std::string _geomType, std::string _styleName, GLenum _drawMode) : Style(_geomType, _styleName, _drawMode) {

    // Pass in a fileName or a url to construct shader strings from
    m_vertShaderSrcStr =
        "#ifdef GL_ES\n"
        "precision mediump float;\n"
        "#endif\n"
        "uniform mat4 u_modelViewProj;\n"
        "attribute vec4 a_position;\n"
        "attribute vec4 a_color;\n"
        "varying vec4 v_color;\n"
        "void main() {\n"
        "  v_color = a_color;\n"
        "  gl_Position = u_modelViewProj * a_position;\n"
        "}\n";

    m_fragShaderSrcStr =
        "#ifdef GL_ES\n"
        "precision mediump float;\n"
        "#endif\n"
        "varying vec4 v_color;\n"
        "void main(void) {\n"
        "  gl_FragColor = v_color;\n"
        "}\n";

    constructVertexLayout();
    constructShaderProgram();
}

PolygonStyle::PolygonStyle(std::string _geomType, GLenum _drawMode) : PolygonStyle(_geomType, _geomType, _drawMode) {}

void PolygonStyle::constructVertexLayout() {
    // fixed per style... this is basic position, normal color
    m_vertexLayout = std::shared_ptr<VertexLayout>(new VertexLayout({
        {"a_position", 3, GL_FLOAT, false, 0},
        {"a_normal", 3, GL_FLOAT, false, 0},
        {"a_color", 4, GL_UNSIGNED_BYTE, true, 0}
    }));
}

void PolygonStyle::constructShaderProgram() {
    m_shaderProgram = std::shared_ptr<ShaderProgram>(new ShaderProgram());
    m_shaderProgram->buildFromSourceStrings(m_fragShaderSrcStr, m_vertShaderSrcStr);
}

void PolygonStyle::addData(const Json::Value& _jsonRoot, MapTile& _tile, const MapProjection& _mapProjection) {
    // Create a vboMesh which will eventually contain all the data
    std::unique_ptr<VboMesh> mesh(new VboMesh(m_vertexLayout, m_drawMode));

    //Extract Feature Properties
    for(auto& layer : m_layerColorMap) {
        Json::Value layerFeatures = _jsonRoot[layer.first.c_str()]["features"];
        //iterate through all features and check for respective geometry type
        for(int i = 0; i < layerFeatures.size(); i++) {
            if(m_geomType.compare(JsonExtractor::extractGeomType(layerFeatures[i])) == 0) {
                std::vector<glm::vec3> extractedGeomCoords;
                std::vector<int> polyRingSizes;
                float featureHeight = 0;
                float minFeatureHeight = 0;
                JsonExtractor::extractGeomCoords(extractedGeomCoords, polyRingSizes, layerFeatures[i], _tile.getOrigin(), _mapProjection);
                GeometryHandler::buildPolygon(extractedGeomCoords, polyRingSizes, m_vertCoords, m_vertNormals, m_indices);

                JsonExtractor::extractFeatureHeightProps(layerFeatures[i], featureHeight, minFeatureHeight);
                if(featureHeight != minFeatureHeight) {
                    GeometryHandler::buildPolygonExtrusion(extractedGeomCoords, polyRingSizes, minFeatureHeight, m_vertCoords, m_vertNormals, m_indices);
                }
                /* fill style's m_vertices with vertCoord, vertNormal and color data */
                fillVertexData(layer.second);
            }
            else {
                continue;
            }
        }
    }
    if(m_vertices.size() == 0) {
        //Nothing to add to mesh, get rid of mesh
        mesh.reset(nullptr);
    }
    else {
        //Add vertices to mesh
        mesh->addVertices((GLbyte*)m_vertices.data(), (int)m_vertices.size());
        mesh->addIndices(m_indices.data(), (int)m_indices.size());
        //1. addGeometry should take either take the name of the style or pointer to the style (this)
        _tile.addGeometry(*this, std::move(mesh));
    }
}

void PolygonStyle::fillVertexData(const GLuint& _abgr) {
    for(int i = (int)m_vertices.size(); i < m_vertCoords.size(); i++) {
        m_vertices.push_back( { m_vertCoords[i].x, m_vertCoords[i].y, m_vertCoords[i].z,
                                m_vertNormals[i].x, m_vertNormals[i].y, m_vertNormals[i].z,
                                _abgr
                              });
    }
    return;
}

void PolygonStyle::clearStyleData() {
    m_vertices.clear();
    m_indices.clear();
    m_vertCoords.clear();
    m_vertNormals.clear();
}

void PolygonStyle::setup() {
}

/*
 * MultiPolygon Style Class Methods
 */

MultiPolygonStyle::MultiPolygonStyle(std::string _geomType, std::string _styleName, GLenum _drawMode) : Style(_geomType, _styleName, _drawMode) {

    // Pass in a fileName or a url to construct shader strings from
    m_vertShaderSrcStr =
        "#ifdef GL_ES\n"
        "precision mediump float;\n"
        "#endif\n"
        "uniform mat4 u_modelViewProj;\n"
        "attribute vec4 a_position;\n"
        "attribute vec4 a_color;\n"
        "varying vec4 v_color;\n"
        "void main() {\n"
        "  v_color = a_color;\n"
        "  gl_Position = u_modelViewProj * a_position;\n"
        "}\n";

    m_fragShaderSrcStr =
        "#ifdef GL_ES\n"
        "precision mediump float;\n"
        "#endif\n"
        "varying vec4 v_color;\n"
        "void main(void) {\n"
        "  gl_FragColor = v_color;\n"
        "}\n";

    constructVertexLayout();
    constructShaderProgram();
}

MultiPolygonStyle::MultiPolygonStyle(std::string _geomType, GLenum _drawMode) : MultiPolygonStyle(_geomType, _geomType, _drawMode) {}

void MultiPolygonStyle::constructVertexLayout() {
    // fixed per style... this is basic position, normal color
    m_vertexLayout = std::shared_ptr<VertexLayout>(new VertexLayout({
        {"a_position", 3, GL_FLOAT, false, 0},
        {"a_normal", 3, GL_FLOAT, false, 0},
        {"a_color", 4, GL_UNSIGNED_BYTE, true, 0}
    }));
}

void MultiPolygonStyle::constructShaderProgram() {
    m_shaderProgram = std::shared_ptr<ShaderProgram>(new ShaderProgram());
    m_shaderProgram->buildFromSourceStrings(m_fragShaderSrcStr, m_vertShaderSrcStr);
}

void MultiPolygonStyle::addData(const Json::Value& _jsonRoot, MapTile& _tile, const MapProjection& _mapProjection) {
    // Create a vboMesh which will eventually contain all the data
    std::unique_ptr<VboMesh> mesh(new VboMesh(m_vertexLayout, m_drawMode));

    //Extract Feature Properties
    for(auto& layer : m_layerColorMap) {
        Json::Value layerFeatures = _jsonRoot[layer.first.c_str()]["features"];
        //iterate through all features and check for respective geometry type
        for(int i = 0; i < layerFeatures.size(); i++) {
            if(m_geomType.compare(JsonExtractor::extractGeomType(layerFeatures[i])) == 0) {
                int numPolys = JsonExtractor::extractNumPoly(layerFeatures[i]);
                float featureHeight = 0;
                float minFeatureHeight = 0;
                std::vector<glm::vec3> extractedGeomCoords;
                std::vector<int> polyRingSizes;
                JsonExtractor::extractGeomCoords(extractedGeomCoords, polyRingSizes, layerFeatures[i], _tile.getOrigin(), _mapProjection, numPolys);
                GeometryHandler::buildPolygon(extractedGeomCoords, polyRingSizes, m_vertCoords, m_vertNormals, m_indices);
                JsonExtractor::extractFeatureHeightProps(layerFeatures[i], featureHeight, minFeatureHeight);
                if(featureHeight != minFeatureHeight) {
                    GeometryHandler::buildPolygonExtrusion(extractedGeomCoords, polyRingSizes, minFeatureHeight, m_vertCoords, m_vertNormals, m_indices);
                }
                /* fill style's m_vertices with vertCoord, vertNormal and color data */
                fillVertexData(layer.second);
            }
            else {
                continue;
            }
        }
    }
    if(m_vertices.size() == 0) {
        //Nothing to add to mesh, get rid of mesh
        mesh.reset(nullptr);
    }
    else {
        //Add vertices to mesh
        mesh->addVertices((GLbyte*)m_vertices.data(), m_vertices.size());
        mesh->addIndices((GLushort*)m_indices.data(), m_indices.size());
        //1. addGeometry should take either take the name of the style or pointer to the style (this)
        _tile.addGeometry(*this, std::move(mesh));
    }
}

void MultiPolygonStyle::fillVertexData(const GLuint& _abgr) {
    for(int i = m_vertices.size(); i < m_vertCoords.size(); i++) {
        m_vertices.push_back( { m_vertCoords[i].x, m_vertCoords[i].y, m_vertCoords[i].z,
                                m_vertNormals[i].x, m_vertNormals[i].y, m_vertNormals[i].z,
                                _abgr
                              });
    }
    return;
}

void MultiPolygonStyle::clearStyleData() {
    m_vertices.clear();
    m_indices.clear();
    m_vertCoords.clear();
    m_vertNormals.clear();
}

void MultiPolygonStyle::setup() {
}
<|endoftext|>


<commit_before>/*
 * Stack.cpp
 *
 *  Created on: 24 Oct 2015
 *      Author: hieu
 */
#include <algorithm>
#include <boost/foreach.hpp>
#include "Stack.h"
#include "Hypothesis.h"
#include "../Scores.h"

using namespace std;

Stack::Stack() {
	// TODO Auto-generated constructor stub

}

Stack::~Stack() {
	// TODO Auto-generated destructor stub
}

void Stack::Add(const Hypothesis *hypo, Recycler<Hypothesis*> &hypoRecycle)
{
	StackAdd added = Add(hypo);

	if (added.toBeDeleted) {
		hypoRecycle.Add(added.toBeDeleted);
	}
}

StackAdd Stack::Add(const Hypothesis *hypo)
{
  std::pair<iterator, bool> addRet = m_hypos.insert(hypo);
  if (addRet.second) {
    // equiv hypo doesn't exists
	return StackAdd(true, NULL);
  }
  else {
	  const Hypothesis *hypoExisting = *addRet.first;
	  if (hypo->GetScores().GetTotalScore() > hypoExisting->GetScores().GetTotalScore()) {
		  // incoming hypo is better than the one we have
		  m_hypos.erase(addRet.first);

		  // re-add. It better go in
		  std::pair<iterator, bool> addRet = m_hypos.insert(hypo);
		  assert(addRet.second);

		  return StackAdd(true, const_cast<Hypothesis*>(hypoExisting));
		  /*
		  const_cast<Hypothesis*>(hypo)->Swap(*const_cast<Hypothesis*>(hypoExisting));
		  return StackAdd(true, const_cast<Hypothesis*>(hypo));
		  */
	  }
	  else {
		  // already storing the best hypo. discard incoming hypo
		  return StackAdd(false, const_cast<Hypothesis*>(hypo));
	  }
  }
}

std::vector<const Hypothesis*> Stack::GetBestHyposAndPrune(size_t num, Recycler<Hypothesis*> &recycler) const
{
  std::vector<const Hypothesis*> ret = GetBestHypos(num);
  if (num && ret.size() > num) {
	  for (size_t i = num; i < ret.size(); ++i) {
		  Hypothesis *hypo = const_cast<Hypothesis*>(ret[i]);
		  recycler.Add(hypo);
	  }
	  ret.resize(num);
  }
  return ret;
}

std::vector<const Hypothesis*> Stack::GetBestHypos(size_t num) const
{
  std::vector<const Hypothesis*> ret(m_hypos.begin(), m_hypos.end());

  std::vector<const Hypothesis*>::iterator iterMiddle;
  iterMiddle = (num == 0 || ret.size() < num)
			   ? ret.end()
			   : ret.begin()+num;

  std::partial_sort(ret.begin(), iterMiddle, ret.end(),
		  HypothesisFutureScoreOrderer());

  return ret;
}

<commit_msg>force new hypo into stack<commit_after>/*
 * Stack.cpp
 *
 *  Created on: 24 Oct 2015
 *      Author: hieu
 */
#include <algorithm>
#include <boost/foreach.hpp>
#include "Stack.h"
#include "Hypothesis.h"
#include "../Scores.h"

using namespace std;

Stack::Stack() {
	// TODO Auto-generated constructor stub

}

Stack::~Stack() {
	// TODO Auto-generated destructor stub
}

void Stack::Add(const Hypothesis *hypo, Recycler<Hypothesis*> &hypoRecycle)
{
	StackAdd added = Add(hypo);

	if (added.toBeDeleted) {
		hypoRecycle.Add(added.toBeDeleted);
	}
}

StackAdd Stack::Add(const Hypothesis *hypo)
{
  std::pair<iterator, bool> addRet = m_hypos.insert(hypo);
  if (addRet.second) {
    // equiv hypo doesn't exists
	return StackAdd(true, NULL);
  }
  else {
	  const Hypothesis *hypoExisting = *addRet.first;
	  if (hypo->GetScores().GetTotalScore() > hypoExisting->GetScores().GetTotalScore()) {
		  // incoming hypo is better than the one we have

		  const Hypothesis *const &h1 = *addRet.first;
		  const Hypothesis *&h2 = const_cast<const Hypothesis *&>(h1);
		  h2 = hypo;

		  return StackAdd(true, const_cast<Hypothesis*>(hypoExisting));
		  /*
		  const_cast<Hypothesis*>(hypo)->Swap(*const_cast<Hypothesis*>(hypoExisting));
		  return StackAdd(true, const_cast<Hypothesis*>(hypo));
		  */
	  }
	  else {
		  // already storing the best hypo. discard incoming hypo
		  return StackAdd(false, const_cast<Hypothesis*>(hypo));
	  }
  }
}

std::vector<const Hypothesis*> Stack::GetBestHyposAndPrune(size_t num, Recycler<Hypothesis*> &recycler) const
{
  std::vector<const Hypothesis*> ret = GetBestHypos(num);
  if (num && ret.size() > num) {
	  for (size_t i = num; i < ret.size(); ++i) {
		  Hypothesis *hypo = const_cast<Hypothesis*>(ret[i]);
		  recycler.Add(hypo);
	  }
	  ret.resize(num);
  }
  return ret;
}

std::vector<const Hypothesis*> Stack::GetBestHypos(size_t num) const
{
  std::vector<const Hypothesis*> ret(m_hypos.begin(), m_hypos.end());

  std::vector<const Hypothesis*>::iterator iterMiddle;
  iterMiddle = (num == 0 || ret.size() < num)
			   ? ret.end()
			   : ret.begin()+num;

  std::partial_sort(ret.begin(), iterMiddle, ret.end(),
		  HypothesisFutureScoreOrderer());

  return ret;
}

<|endoftext|>


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

#ifndef _RECORD_HPP
#define _RECORD_HPP

#include "config.hpp"
#include "field.hpp"            // for fp::field
#include "int_sequence.hpp"     // for fp::index_of
#include "type_traits.hpp"      // for fp::EnableIf, fp::DisableIf

#include <tuple>        // for std::tuple, std::get

namespace fp {
    template<typename...>
    struct record;

    // This sole purpose of this declaration is to enable ADL
    template<typename> void get() = delete;

    template<typename>
    struct is_record : Bool<false> { };

    template<typename... TFields>
    struct is_record<record<TFields...> > : All<is_field<TFields>...> { };

    template<>
    struct record<> {
        template<typename... TOther>
        struct rebind {
            using type = record<TOther...>;
        };
    };

    template<typename... TFields>
    struct record {
    public:

        template<typename... TOther>
        struct rebind {
            using type = record<TOther...>;
        };

        template<std::size_t Idx>
        struct nth_type {
            using type = NthTypeOf<Idx, Invoke<TFields>...>;
        };
    protected:
        std::tuple<Invoke<TFields>...> _values;
    public:

        constexpr record()
        : _values() {
        }

        constexpr record(Invoke<TFields>... fs)
        : _values(std::move(fs)...) {
        }

        record(record const & rec)
        : _values(rec._values) {
        }

        record(record && rec) noexcept
        : _values() {
            swap(*this, rec);
        }

        friend void swap(record & l, record & r) noexcept {
            using std::swap;
            swap(l._values, r._values);
        }

        constexpr static std::size_t size() {
            return sizeof...(TFields);
        }

        template<std::size_t Idx>
        friend Invoke<nth_type<index_of<Idx, TFields::index...>::value>> & get(record & rec) {
            return std::get<index_of<Idx, TFields::index...>::value>(rec._values);
        }

        template<std::size_t Idx>
        friend Invoke<nth_type<index_of<Idx, TFields::index...>::value>> const & get(record const & rec) {
            return std::get<index_of<Idx, TFields::index...>::value>(rec._values);
        }

        template<typename TField, EnableIf<is_field<TField>> = _>
        friend Invoke<TField> & get(record & rec) {
            return get<TField::index>(rec);
        }

        template<typename TField, EnableIf<is_field<TField>> = _>
        friend Invoke<TField> const & get(record const & rec) {
            return get<TField::index>(rec);
        }
    };
}

#endif<commit_msg>added default copy-constructor, move-constructor, copy-assignment, and move-assignment operator<commit_after>/* 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/. */

#ifndef _RECORD_HPP
#define _RECORD_HPP

#include "config.hpp"
#include "field.hpp"            // for fp::field
#include "int_sequence.hpp"     // for fp::index_of
#include "type_traits.hpp"      // for fp::EnableIf, fp::DisableIf

#include <tuple>        // for std::tuple, std::get

namespace fp {
    template<typename...>
    struct record;

    // This sole purpose of this declaration is to enable ADL
    template<typename> void get() = delete;

    template<typename>
    struct is_record : Bool<false> { };

    template<typename... TFields>
    struct is_record<record<TFields...> > : All<is_field<TFields>...> { };

    template<>
    struct record<> {
        template<typename... TOther>
        struct rebind {
            using type = record<TOther...>;
        };
    };

    template<typename... TFields>
    struct record {
    public:

        template<typename... TOther>
        struct rebind {
            using type = record<TOther...>;
        };

        template<std::size_t Idx>
        struct nth_type {
            using type = NthTypeOf<Idx, Invoke<TFields>...>;
        };
    protected:
        std::tuple<Invoke<TFields>...> _values;
    public:

        constexpr record() = default;

        record(record const &) = default;

        record(record && rec) = default;

        constexpr record(Invoke<TFields>... fs)
        : _values(std::move(fs)...) {
        }

        record & operator=(record const &) = default;
        record & operator=(record &&) = default;

        friend void swap(record & l, record & r) noexcept {
            using std::swap;
            swap(l._values, r._values);
        }

        constexpr static std::size_t size() {
            return sizeof...(TFields);
        }

        template<std::size_t Idx>
        friend Invoke<nth_type<index_of<Idx, TFields::index...>::value>> & get(record & rec) {
            return std::get<index_of<Idx, TFields::index...>::value>(rec._values);
        }

        template<std::size_t Idx>
        friend Invoke<nth_type<index_of<Idx, TFields::index...>::value>> const & get(record const & rec) {
            return std::get<index_of<Idx, TFields::index...>::value>(rec._values);
        }

        template<typename TField, EnableIf<is_field<TField>> = _>
        friend Invoke<TField> & get(record & rec) {
            return get<TField::index>(rec);
        }

        template<typename TField, EnableIf<is_field<TField>> = _>
        friend Invoke<TField> const & get(record const & rec) {
            return get<TField::index>(rec);
        }
    };
}

#endif<|endoftext|>


<commit_before>#pragma once

#include "amd64.h"
#ifdef XV6_KERNEL
#include "atomic.hh"
#else
#include <atomic>
#endif

/**
 * A seqcount is a synchronization primitive that, in conjunction with
 * some form of mutual exclusion, provides write-free optimistic reads
 * of shared data.
 */
template<typename T = unsigned>
class seqcount
{
  std::atomic<T> seq_;

public:
  constexpr seqcount() : seq_(0) { }

  /**
   * An RAII object representing a read section protected by a
   * seqcount.
   */
  class reader
  {
    seqcount * const sc_;
    T init_;

  public:
    constexpr reader(seqcount *sc, T init) : sc_(sc), init_(init) { }

    /**
     * Return true if this read section needs to be retried because of
     * an intervening write section.
     */
    bool need_retry() const
    {
      // The release fence prevents code (specifically, reads) from
      // sinking below the check.
      std::atomic_thread_fence(std::memory_order_release);
      return sc_->seq_.load(std::memory_order_relaxed) != init_;
    }

    T count() const
    {
      return init_;
    }
  };

  /**
   * Signal the beginning of a read of the shared data protected by
   * this seqcount.  This read is opportunistic, so after reading the
   * data, the caller must call #reader::need_retry() on the returned
   * object and, if it returns true, restart the read (including the
   * read_begin()).  Note that the reader must assume that any data
   * returned before need_retry() returns false may be garbage (for
   * example, it's not safe to follow pointers without additional
   * protection from something like RCU).
   */
  reader read_begin()
  {
  retry:
    // Acquire order disables code hoisting so that reads in the
    // caller don't move before our counter snapshot.  Furthermore,
    // this synchronizes with the release store in writer::done such
    // that, if we observe its write, we will observe all writes
    // before it.
    auto s = seq_.load(std::memory_order_acquire);
    if (s & 1) {
      nop_pause();
      goto retry;
    }
    return reader(this, s);
  }

  /**
   * An RAII section representing a write section that may conflict
   * with read sections managed by a seqcount.
   */
  class writer
  {
    seqcount *sc_;
    T val_;

  public:
    constexpr writer(seqcount *sc, T val) : sc_(sc), val_(val) { }

    /**
     * End the write section.
     */
    ~writer()
    {
      done();
    }

    /**
     * End the write section.
     */
    void done() __attribute__((always_inline))
    {
      if (sc_) {
        // This is the mirror of write_begin: writes are not allowed
        // to move after this, but reads are.
        sc_->seq_.store(val_ + 1, std::memory_order_release);
        sc_ = nullptr;
      }
    }
  };

  /**
   * Begin a write section.  This alone does not synchronize write
   * sections; the caller is responsible for acquiring some other form
   * of mutual exclusion before this and releasing it after ending the
   * write section.
   *
   * Another thread attempting to start a reads will spin until this
   * write section ends.  If another thread is currently in a read
   * section, it will be forced to retry.
   */
  writer write_begin()
  {
    // Writes are not allowed to move before this because they may be
    // observed by a reader that thinks the value is stable.  Reads
    // are allowed to move before this because they cannot affect the
    // value observed by readers (and the caller is required to
    // precede this with a lock acquire, which is a stronger barrier).
    // Furthermore, because the caller provides mutual exclusion, we
    // don't have to worry about competing writes, so we don't need an
    // interlocked increment.
    //
    // Because of the surrounding synchronization, we use relaxed
    // ordering for the load and store (the stronger barrier of the
    // lock will prevent even these from hoisting).  To ensure nothing
    // after the store hoists, we follow it with an acquire fence.
    T val = seq_.load(std::memory_order_relaxed);
    seq_.store(val + 1, std::memory_order_relaxed);
    std::atomic_thread_fence(std::memory_order_acquire);
    return writer(this, val + 1);
  }
};
<commit_msg>export seqcount value too<commit_after>#pragma once

#include "amd64.h"
#ifdef XV6_KERNEL
#include "atomic.hh"
#else
#include <atomic>
#endif

/**
 * A seqcount is a synchronization primitive that, in conjunction with
 * some form of mutual exclusion, provides write-free optimistic reads
 * of shared data.
 */
template<typename T = unsigned>
class seqcount
{
  std::atomic<T> seq_;

public:
  constexpr seqcount() : seq_(0) { }

  /**
   * An RAII object representing a read section protected by a
   * seqcount.
   */
  class reader
  {
    seqcount * const sc_;
    T init_;

  public:
    constexpr reader(seqcount *sc, T init) : sc_(sc), init_(init) { }

    /**
     * Return true if this read section needs to be retried because of
     * an intervening write section.
     */
    bool need_retry() const
    {
      // The release fence prevents code (specifically, reads) from
      // sinking below the check.
      std::atomic_thread_fence(std::memory_order_release);
      return sc_->seq_.load(std::memory_order_relaxed) != init_;
    }

    T count() const
    {
      return init_;
    }
  };

  /**
   * Signal the beginning of a read of the shared data protected by
   * this seqcount.  This read is opportunistic, so after reading the
   * data, the caller must call #reader::need_retry() on the returned
   * object and, if it returns true, restart the read (including the
   * read_begin()).  Note that the reader must assume that any data
   * returned before need_retry() returns false may be garbage (for
   * example, it's not safe to follow pointers without additional
   * protection from something like RCU).
   */
  reader read_begin()
  {
  retry:
    // Acquire order disables code hoisting so that reads in the
    // caller don't move before our counter snapshot.  Furthermore,
    // this synchronizes with the release store in writer::done such
    // that, if we observe its write, we will observe all writes
    // before it.
    auto s = seq_.load(std::memory_order_acquire);
    if (s & 1) {
      nop_pause();
      goto retry;
    }
    return reader(this, s);
  }

  /**
   * An RAII section representing a write section that may conflict
   * with read sections managed by a seqcount.
   */
  class writer
  {
    seqcount *sc_;
    T val_;

  public:
    constexpr writer(seqcount *sc, T val) : sc_(sc), val_(val) { }

    /**
     * End the write section.
     */
    ~writer()
    {
      done();
    }

    /**
     * End the write section.
     */
    void done() __attribute__((always_inline))
    {
      if (sc_) {
        // This is the mirror of write_begin: writes are not allowed
        // to move after this, but reads are.
        sc_->seq_.store(val_ + 1, std::memory_order_release);
        sc_ = nullptr;
      }
    }
  };

  /**
   * Begin a write section.  This alone does not synchronize write
   * sections; the caller is responsible for acquiring some other form
   * of mutual exclusion before this and releasing it after ending the
   * write section.
   *
   * Another thread attempting to start a reads will spin until this
   * write section ends.  If another thread is currently in a read
   * section, it will be forced to retry.
   */
  writer write_begin()
  {
    // Writes are not allowed to move before this because they may be
    // observed by a reader that thinks the value is stable.  Reads
    // are allowed to move before this because they cannot affect the
    // value observed by readers (and the caller is required to
    // precede this with a lock acquire, which is a stronger barrier).
    // Furthermore, because the caller provides mutual exclusion, we
    // don't have to worry about competing writes, so we don't need an
    // interlocked increment.
    //
    // Because of the surrounding synchronization, we use relaxed
    // ordering for the load and store (the stronger barrier of the
    // lock will prevent even these from hoisting).  To ensure nothing
    // after the store hoists, we follow it with an acquire fence.
    T val = seq_.load(std::memory_order_relaxed);
    seq_.store(val + 1, std::memory_order_relaxed);
    std::atomic_thread_fence(std::memory_order_acquire);
    return writer(this, val + 1);
  }

  T count() const
  {
    // XXX what memory order should we use here?
    return seq_.load();
  }
};
<|endoftext|>


<commit_before>// Time:  O(n)
// Space: O(1)

class Solution {
public:
    bool isSelfCrossing(vector<int>& x) {
        for (int i = 3; i < x.size(); ++i) {
            if (x[i] >= x[i - 2] && x[i - 3] >= x[i - 1]) {
//                          i-2
//              case 1 : i-1┌─┐
//                          └─┼─>i
//                           i-3
                return true;
            } else if (i >= 4 && x[i - 1] == x[i - 3] && x[i] + x[i - 4] >= x[i - 2]) {
//                          i-2
//              case 2 : i-1┌────┐
//                          └─══>┘i-3
//                          i  i-4  (overlapped)
                return true;
            } else if (i >= 5 && x[i - 4] <= x[i - 2] && x[i] + x[i - 4] >= x[i - 2] &&
                       x[i - 1] <= x[i - 3] && x[i - 1] + x[i - 5] >= x[i - 3]) {
//                          i-4
//                          ┌──┐
//              case 3 :    │i<┼─┐
//                       i-3│ i-5│i-1
//                          └────┘
//                          i-2
                return true;
            }
        }
        return false;
    }
};
<commit_msg>Update self-crossing.cpp<commit_after>// Time:  O(n)
// Space: O(1)

class Solution {
public:
    bool isSelfCrossing(vector<int>& x) {
        if (x.size() >= 5 && x[3] == x[1] && x[4] + x[0] >= x[2]) {
            // Crossing in a loop:
            //     i-2
            // i-1┌────┐
            //    └─══>┘i-3
            //    i i-4  (overlapped)
            return true;
        }

        for (int i = 3; i < x.size(); ++i) {
            if (x[i] >= x[i - 2] && x[i - 3] >= x[i - 1]) {
                // Crossing in a shrinking spiral:
                //    i-2
                // i-1┌─┐
                //    └─┼─>i
                //     i-3
                return true;
            } else if (i >= 5 && x[i - 4] <= x[i - 2] && x[i] + x[i - 4] >= x[i - 2] &&
                       x[i - 1] <= x[i - 3] && x[i - 1] + x[i - 5] >= x[i - 3]) {
                // Crossing in a growing spiral:
                //    i-4
                //    ┌──┐
                //    │i<┼─┐
                // i-3│ i-5│i-1
                //    └────┘
                // i-2
                return true;
            }
        }
        return false;
    }
};
<|endoftext|>


<commit_before>// geometry_rect.C -- Horizontal and vertical grid lines.
//
// Copyright 2006 Per Abrahamsen and KVL.
//
// This file is part of Daisy.
//
// Daisy is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// Daisy is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser Public License for more details.
//
// You should have received a copy of the GNU Lesser Public License
// along with Daisy; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#include "geometry_rect.h"
#include "check.h"
#include "vcheck.h"
#include "block.h"
#include "submodel.h"
#include <sstream>

size_t
GeometryRect::cell_at (const double z, const double x, const double) const
{
  size_t cell = 0;
  while (zplus_[cell] > z)
    {
      cell++;
      daisy_assert (cell < cell_size ());
    }
  while (xplus_[cell] < x)
    {
      cell += cell_columns_;
      daisy_assert (cell < cell_size ());
    }
  return cell;
}

double
GeometryRect::fraction_in_z_interval (const size_t i,
                                      const double from, const double to) const
{ return fraction_within (zplus (i), zminus (i), to, from); }

bool
GeometryRect::contain_z (const size_t i, const double z) const
{
  daisy_assert (zminus (i) > zplus (i));
  return  zminus (i) > z && z >= zplus (i);
}

bool
GeometryRect::check (Treelog&) const
{
  bool ok = true;
  return ok;
}

bool
GeometryRect::check_border (const double border, Treelog& err) const
{
  bool ok = false;

  for (size_t i = 0; i < cell_rows_; i++)
    if (approximate (border, zplus (i)))
      ok = true;

  if (!ok)
    {
      std::ostringstream tmp;
      tmp << "No geometric border near " << border
             << " [cm], log results may be inexact";
      err.warning (tmp.str ());
    }

  return ok;
}

void
GeometryRect::load_syntax (Syntax& syntax, AttributeList&)
{
  alist.add ("submodel", "GeometryRect");
  syntax.add ("zplus", "cm", Check::negative (),
	      Syntax::Const, Syntax::Sequence,
	      "Depth of each numeric layer (a negative number).\n\
The end points are listed descending from the surface to the bottom.");
  static VCheck::All zplus_check (VCheck::decreasing (),
				  VCheck::min_size_1 ());
  syntax.add_check ("zplus", zplus_check);
  syntax.add ("xplus", "cm", Check::positive (),
	      Syntax::Const, Syntax::Sequence,
	      "Horizontal end of each numeric layer (a positive number).\n\
The end points are listed ascending from left (0.0) to right.");
  static VCheck::All xplus_check (VCheck::increasing (),
				  VCheck::min_size_1 ());
  syntax.add_check ("xplus", xplus_check);
}

GeometryRect::GeometryRect (Block& al)
  : GeometryVert (al),
    cell_rows_ (al.number_sequence ("zplus").size ()),
    cell_columns_ (al.number_sequence ("xplus").size ())
{
  // Initialize base.
  size_ = cell_columns () * cell_rows ();

  // Extract grid information from parameters.
  const std::vector<double> z_end (al.number_sequence ("zplus"));
  std::vector<double> z_center;
  std::vector<double> z_distance;
  initialize_intervals (z_end, z_center, z_distance);
  const std::vector<double> x_end (al.number_sequence ("xplus"));
  std::vector<double> x_center;
  std::vector<double> x_distance;
  initialize_intervals (x_end, x_center, x_distance);

  // Fill in cells by column, starting from the top left corner.
  size_t next_cell = 0;
  for (size_t column = 0; column < cell_columns (); column++)
    {
      // Top edge.
      size_t last_cell = cell_above;

      for (size_t row = 0; row < cell_rows (); row++)
        {
          // Cell
          zplus_.push_back (z_end[row]);
          z_.push_back (z_center[row]);
          dz_.push_back (z_distance[row]);
          xplus_.push_back (x_end[column]);
          x_.push_back (x_center[column]);
          dx_.push_back (x_distance[column]);
          // Vertical edge.
          edge_from_.push_back (next_cell);
          edge_to_.push_back (last_cell);
          edge_area_.push_back (x_distance[column]);
          // Next node.
          daisy_assert (next_cell == cell_index (row, column));
          last_cell = next_cell;
          next_cell++;
        }
      // Bottom edge.
      edge_from_.push_back (cell_below);
      edge_to_.push_back (last_cell);
      edge_area_.push_back (x_distance[column]);
    }
  daisy_assert (next_cell == cell_size ());

  // Horizontal edges.
  for (size_t row = 0; row < cell_rows (); row++)
    for (size_t column = 0; column < edge_columns (); column++)
      {
        edge_from_.push_back (cell_index (row, column));
        edge_to_.push_back (cell_index (row, column + 1));
        edge_area_.push_back (z_distance[row]);
      }

  // Done.
  daisy_assert (edge_area_.size () == edge_to_.size ());
  daisy_assert (edge_from_.size () == edge_to_.size ());
  daisy_assert (edge_size () == (edge_rows () * cell_columns ()
                                 + edge_columns () * cell_rows ()));
}

GeometryRect::~GeometryRect ()
{ }

static Submodel::Register
geometry_rect_submodel ("GeometryRect", GeometryRect::load_syntax);
<commit_msg>Version 4.03<commit_after>// geometry_rect.C -- Horizontal and vertical grid lines.
//
// Copyright 2006 Per Abrahamsen and KVL.
//
// This file is part of Daisy.
//
// Daisy is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// Daisy is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser Public License for more details.
//
// You should have received a copy of the GNU Lesser Public License
// along with Daisy; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#include "geometry_rect.h"
#include "check.h"
#include "vcheck.h"
#include "block.h"
#include "submodel.h"
#include <sstream>

size_t
GeometryRect::cell_at (const double z, const double x, const double) const
{
  size_t cell = 0;
  while (zplus_[cell] > z)
    {
      cell++;
      daisy_assert (cell < cell_size ());
    }
  while (xplus_[cell] < x)
    {
      cell += cell_columns_;
      daisy_assert (cell < cell_size ());
    }
  return cell;
}

double
GeometryRect::fraction_in_z_interval (const size_t i,
                                      const double from, const double to) const
{ return fraction_within (zplus (i), zminus (i), to, from); }

bool
GeometryRect::contain_z (const size_t i, const double z) const
{
  daisy_assert (zminus (i) > zplus (i));
  return  zminus (i) > z && z >= zplus (i);
}

bool
GeometryRect::check (Treelog&) const
{
  bool ok = true;
  return ok;
}

bool
GeometryRect::check_border (const double border, Treelog& err) const
{
  bool ok = false;

  for (size_t i = 0; i < cell_rows_; i++)
    if (approximate (border, zplus (i)))
      ok = true;

  if (!ok)
    {
      std::ostringstream tmp;
      tmp << "No geometric border near " << border
             << " [cm], log results may be inexact";
      err.warning (tmp.str ());
    }

  return ok;
}

void
GeometryRect::load_syntax (Syntax& syntax, AttributeList& alist)
{
  alist.add ("submodel", "GeometryRect");
  syntax.add ("zplus", "cm", Check::negative (),
	      Syntax::Const, Syntax::Sequence,
	      "Depth of each numeric layer (a negative number).\n\
The end points are listed descending from the surface to the bottom.");
  static VCheck::All zplus_check (VCheck::decreasing (),
				  VCheck::min_size_1 ());
  syntax.add_check ("zplus", zplus_check);
  syntax.add ("xplus", "cm", Check::positive (),
	      Syntax::Const, Syntax::Sequence,
	      "Horizontal end of each numeric layer (a positive number).\n\
The end points are listed ascending from left (0.0) to right.");
  static VCheck::All xplus_check (VCheck::increasing (),
				  VCheck::min_size_1 ());
  syntax.add_check ("xplus", xplus_check);
}

GeometryRect::GeometryRect (Block& al)
  : GeometryVert (al),
    cell_rows_ (al.number_sequence ("zplus").size ()),
    cell_columns_ (al.number_sequence ("xplus").size ())
{
  // Initialize base.
  size_ = cell_columns () * cell_rows ();

  // Extract grid information from parameters.
  const std::vector<double> z_end (al.number_sequence ("zplus"));
  std::vector<double> z_center;
  std::vector<double> z_distance;
  initialize_intervals (z_end, z_center, z_distance);
  const std::vector<double> x_end (al.number_sequence ("xplus"));
  std::vector<double> x_center;
  std::vector<double> x_distance;
  initialize_intervals (x_end, x_center, x_distance);

  // Fill in cells by column, starting from the top left corner.
  size_t next_cell = 0;
  for (size_t column = 0; column < cell_columns (); column++)
    {
      // Top edge.
      size_t last_cell = cell_above;

      for (size_t row = 0; row < cell_rows (); row++)
        {
          // Cell
          zplus_.push_back (z_end[row]);
          z_.push_back (z_center[row]);
          dz_.push_back (z_distance[row]);
          xplus_.push_back (x_end[column]);
          x_.push_back (x_center[column]);
          dx_.push_back (x_distance[column]);
          // Vertical edge.
          edge_from_.push_back (next_cell);
          edge_to_.push_back (last_cell);
          edge_area_.push_back (x_distance[column]);
          // Next node.
          daisy_assert (next_cell == cell_index (row, column));
          last_cell = next_cell;
          next_cell++;
        }
      // Bottom edge.
      edge_from_.push_back (cell_below);
      edge_to_.push_back (last_cell);
      edge_area_.push_back (x_distance[column]);
    }
  daisy_assert (next_cell == cell_size ());

  // Horizontal edges.
  for (size_t row = 0; row < cell_rows (); row++)
    for (size_t column = 0; column < edge_columns (); column++)
      {
        edge_from_.push_back (cell_index (row, column));
        edge_to_.push_back (cell_index (row, column + 1));
        edge_area_.push_back (z_distance[row]);
      }

  // Done.
  daisy_assert (edge_area_.size () == edge_to_.size ());
  daisy_assert (edge_from_.size () == edge_to_.size ());
  daisy_assert (edge_size () == (edge_rows () * cell_columns ()
                                 + edge_columns () * cell_rows ()));
}

GeometryRect::~GeometryRect ()
{ }

static Submodel::Register
geometry_rect_submodel ("GeometryRect", GeometryRect::load_syntax);
<|endoftext|>