<commit_before>
#include <stdlib.h>
#include <functional>
#include "gpio.h"

#include "utils.h"
#include "odrive_main.hpp"

Axis::Axis(const AxisHardwareConfig_t& hw_config,
           AxisConfig_t& config,
           Encoder& encoder,
           SensorlessEstimator& sensorless_estimator,
           Controller& controller,
           Motor& motor)
    : hw_config_(hw_config),
      config_(config),
      encoder_(encoder),
      sensorless_estimator_(sensorless_estimator),
      controller_(controller),
      motor_(motor)
{
    encoder_.axis_ = this;
    sensorless_estimator_.axis_ = this;
    controller_.axis_ = this;
    motor_.axis_ = this;
}

// @brief Sets up all components of the axis,
// such as gate driver and encoder hardware.
void Axis::setup() {
    encoder_.setup();
    motor_.setup();
}

static void run_state_machine_loop_wrapper(void* ctx) {
    reinterpret_cast<Axis*>(ctx)->run_state_machine_loop();
}

// @brief Starts run_state_machine_loop in a new thread
void Axis::start_thread() {
    osThreadDef(thread_def, run_state_machine_loop_wrapper, hw_config_.thread_priority, 0, 512);
    thread_id_ = osThreadCreate(osThread(thread_def), this);
    thread_id_valid_ = true;
}

// @brief Unblocks the control loop thread.
// This is called from the current sense interrupt handler.
void Axis::signal_current_meas() {
    if (thread_id_valid_)
        osSignalSet(thread_id_, M_SIGNAL_PH_CURRENT_MEAS);
}

// @brief Blocks until a current measurement is completed
// @returns True on success, false otherwise
bool Axis::wait_for_current_meas() {
    if (osSignalWait(M_SIGNAL_PH_CURRENT_MEAS, PH_CURRENT_MEAS_TIMEOUT).status != osEventSignal)
        return error_ = ERROR_CURRENT_MEASUREMENT_TIMEOUT, false;
    return true;
}

static void step_cb_wrapper(void* ctx) {
    reinterpret_cast<Axis*>(ctx)->step_cb();
}

// step/direction interface
void Axis::step_cb() {
    if (enable_step_dir_) {
        GPIO_PinState dir_pin = HAL_GPIO_ReadPin(hw_config_.dir_port, hw_config_.dir_pin);
        float dir = (dir_pin == GPIO_PIN_SET) ? 1.0f : -1.0f;
        controller_.pos_setpoint_ += dir * config_.counts_per_step;
    }
};

// @brief Enables or disables step/dir input
void Axis::set_step_dir_enabled(bool enable) {
    if (enable) {
        // Set up the direction GPIO as input
        GPIO_InitTypeDef GPIO_InitStruct;
        GPIO_InitStruct.Pin = hw_config_.dir_pin;
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        HAL_GPIO_Init(hw_config_.dir_port, &GPIO_InitStruct);

        // Subscribe to rising edges of the step GPIO
        GPIO_subscribe(hw_config_.step_port, hw_config_.step_pin, GPIO_PULLDOWN,
                step_cb_wrapper, this);

        enable_step_dir_ = true;
    } else {
        enable_step_dir_ = false;

        // Unsubscribe from step GPIO
        GPIO_unsubscribe(hw_config_.step_port, hw_config_.step_pin);
    }
}

// @brief Returns true if the power supply is within range
bool Axis::check_PSU_brownout() {
    if(vbus_voltage < config_.dc_bus_brownout_trip_level)
        return error_ = ERROR_BAD_VOLTAGE, false;
    return true;
}

// @brief Returns true if everything is ok.
// Sets error and returns false otherwise.
bool Axis::do_checks() {
    if (!motor_.do_checks())
        return error_ = ERROR_MOTOR_FAILED, false;
    if (!check_PSU_brownout())
        return error_ = ERROR_BAD_VOLTAGE, false;
    return true;
}

bool Axis::run_sensorless_spin_up() {
    // Early Spin-up: spiral up current
    float x = 0.0f;
    run_control_loop([&](){
        float phase = wrap_pm_pi(config_.ramp_up_distance * x);
        float I_mag = config_.spin_up_current * x;
        x += current_meas_period / config_.ramp_up_time;
        if (!motor_.update(I_mag, phase))
            return error_ = ERROR_MOTOR_FAILED, false;
        return x < 1.0f;
    });
    if (error_ != ERROR_NO_ERROR)
        return false;

    // Late Spin-up: accelerate
    float vel = config_.ramp_up_distance / config_.ramp_up_time;
    float phase = wrap_pm_pi(config_.ramp_up_distance);
    run_control_loop([&](){
        vel += config_.spin_up_acceleration * current_meas_period;
        phase = wrap_pm_pi(phase + vel * current_meas_period);
        float I_mag = config_.spin_up_current;
        if (!motor_.update(I_mag, phase))
            return error_ = ERROR_MOTOR_FAILED, false;
        return vel < config_.spin_up_target_vel;
    });
    return error_ == ERROR_NO_ERROR;
}

// Note run_sensorless_control_loop and run_closed_loop_control_loop are very similar and differ only in where we get the estimate from.
bool Axis::run_sensorless_control_loop() {
    set_step_dir_enabled(config_.enable_step_dir);
    run_control_loop([this](){
        float pos_estimate, vel_estimate, phase, current_setpoint;

        if (controller_.config_.control_mode >= CTRL_MODE_POSITION_CONTROL)
            return error_ = ERROR_POS_CTRL_DURING_SENSORLESS, false;

        // We update the encoder just in case someone needs the output for testing
        encoder_.update(nullptr, nullptr, nullptr);
        if (!sensorless_estimator_.update(&pos_estimate, &vel_estimate, &phase))
            return error_ = ERROR_SENSORLESS_ESTIMATOR_FAILED, false;
        if (!controller_.update(pos_estimate, vel_estimate, &current_setpoint))
            return error_ = ERROR_CONTROLLER_FAILED, false;
        if (!motor_.update(current_setpoint, phase))
            return error_ = ERROR_MOTOR_FAILED, false;
        return true;
    });
    set_step_dir_enabled(false);
    return error_ == ERROR_NO_ERROR;
}

bool Axis::run_closed_loop_control_loop() {
    set_step_dir_enabled(config_.enable_step_dir);
    run_control_loop([this](){
        float pos_estimate, vel_estimate, phase, current_setpoint;

        // We update the sensorless estimator just in case someone needs the output for testing
        sensorless_estimator_.update(nullptr, nullptr, nullptr);
        if (!encoder_.update(&pos_estimate, &vel_estimate, &phase))
            return error_ = ERROR_ENCODER_FAILED, false;
        if (!controller_.update(pos_estimate, vel_estimate, &current_setpoint))
            return error_ = ERROR_CONTROLLER_FAILED, false;
        if (!motor_.update(current_setpoint, phase))
            return error_ = ERROR_MOTOR_FAILED, false;
        return true;
    });
    set_step_dir_enabled(false);
    return error_ == ERROR_NO_ERROR;
}

bool Axis::run_idle_loop() {
    // run_control_loop ignores missed modulation timing updates
    // if and only if we're in AXIS_STATE_IDLE
    run_control_loop([this](){
        sensorless_estimator_.update(nullptr, nullptr, nullptr);
        encoder_.update(nullptr, nullptr, nullptr);
        return true;
    });
    return error_ == ERROR_NO_ERROR;
}

// Infinite loop that does calibration and enters main control loop as appropriate
void Axis::run_state_machine_loop() {

    // Allocate the map for anti-cogging algorithm and initialize all values to 0.0f
    // TODO: Move this somewhere else
    // TODO: respect changes of CPR
    int encoder_cpr = encoder_.config_.cpr;
    controller_.anticogging_.cogging_map = (float*)malloc(encoder_cpr * sizeof(float));
    if (controller_.anticogging_.cogging_map != NULL) {
        for (int i = 0; i < encoder_cpr; i++) {
            controller_.anticogging_.cogging_map[i] = 0.0f;
        }
    }

    // arm!
    motor_.arm();

    for (;;) {
        // Load the task chain if a specific request is pending
        if (requested_state_ != AXIS_STATE_UNDEFINED) {
            size_t pos = 0;
            if (requested_state_ == AXIS_STATE_STARTUP_SEQUENCE) {
                if (config_.startup_motor_calibration)
                    task_chain_[pos++] = AXIS_STATE_MOTOR_CALIBRATION;
                if (config_.startup_encoder_calibration)
                    task_chain_[pos++] = AXIS_STATE_ENCODER_CALIBRATION;
                if (config_.startup_closed_loop_control)
                    task_chain_[pos++] = AXIS_STATE_CLOSED_LOOP_CONTROL;
                else if (config_.startup_sensorless_control)
                    task_chain_[pos++] = AXIS_STATE_SENSORLESS_CONTROL;
                task_chain_[pos++] = AXIS_STATE_IDLE;
            } else if (requested_state_ == AXIS_STATE_FULL_CALIBRATION_SEQUENCE) {
                task_chain_[pos++] = AXIS_STATE_MOTOR_CALIBRATION;
                task_chain_[pos++] = AXIS_STATE_ENCODER_CALIBRATION;
                task_chain_[pos++] = AXIS_STATE_IDLE;
            } else if (requested_state_ != AXIS_STATE_UNDEFINED) {
                task_chain_[pos++] = requested_state_;
                task_chain_[pos++] = AXIS_STATE_IDLE;
            }
            task_chain_[pos++] = AXIS_STATE_UNDEFINED;
            // TODO: bounds checking
            requested_state_ = AXIS_STATE_UNDEFINED;
        }

        // Note that current_state is a reference to task_chain_[0]

        // Validate the state before running it
        if (current_state_ > AXIS_STATE_MOTOR_CALIBRATION && !motor_.is_calibrated_)
            current_state_ = AXIS_STATE_UNDEFINED;
        if (current_state_ > AXIS_STATE_ENCODER_CALIBRATION && !encoder_.is_calibrated_)
            current_state_ = AXIS_STATE_UNDEFINED;

        // Run the specified state
        // Handlers should exit if requested_state != AXIS_STATE_UNDEFINED
        bool status;
        switch (current_state_) {
        case AXIS_STATE_MOTOR_CALIBRATION:
            status = motor_.run_calibration();
            break;

        case AXIS_STATE_ENCODER_CALIBRATION:
            status = encoder_.run_calibration();
            break;

        case AXIS_STATE_SENSORLESS_CONTROL:
            status = run_sensorless_spin_up(); // TODO: restart if desired
            if (status)
                status = run_sensorless_control_loop();
            break;

        case AXIS_STATE_CLOSED_LOOP_CONTROL:
            status = run_closed_loop_control_loop();
            break;

        case AXIS_STATE_IDLE:
            run_idle_loop();
            status = motor_.arm(); // done with idling - try to arm the motor
            break;

        default:
            error_ = ERROR_INVALID_STATE;
            status = false; // this will set the state to idle
            break;
        }

        // If the state failed, go to idle, else advance task chain
        if (!status)
            current_state_ = AXIS_STATE_IDLE;
        else
            memcpy(task_chain_, task_chain_ + 1, sizeof(task_chain_) - sizeof(task_chain_[0]));
    }

    thread_id_valid_ = false;
}
<commit_msg>increase axis thread stack size to 2k<commit_after>
#include <stdlib.h>
#include <functional>
#include "gpio.h"

#include "utils.h"
#include "odrive_main.hpp"

Axis::Axis(const AxisHardwareConfig_t& hw_config,
           AxisConfig_t& config,
           Encoder& encoder,
           SensorlessEstimator& sensorless_estimator,
           Controller& controller,
           Motor& motor)
    : hw_config_(hw_config),
      config_(config),
      encoder_(encoder),
      sensorless_estimator_(sensorless_estimator),
      controller_(controller),
      motor_(motor)
{
    encoder_.axis_ = this;
    sensorless_estimator_.axis_ = this;
    controller_.axis_ = this;
    motor_.axis_ = this;
}

// @brief Sets up all components of the axis,
// such as gate driver and encoder hardware.
void Axis::setup() {
    encoder_.setup();
    motor_.setup();
}

static void run_state_machine_loop_wrapper(void* ctx) {
    reinterpret_cast<Axis*>(ctx)->run_state_machine_loop();
}

// @brief Starts run_state_machine_loop in a new thread
void Axis::start_thread() {
    osThreadDef(thread_def, run_state_machine_loop_wrapper, hw_config_.thread_priority, 0, 4*512);
    thread_id_ = osThreadCreate(osThread(thread_def), this);
    thread_id_valid_ = true;
}

// @brief Unblocks the control loop thread.
// This is called from the current sense interrupt handler.
void Axis::signal_current_meas() {
    if (thread_id_valid_)
        osSignalSet(thread_id_, M_SIGNAL_PH_CURRENT_MEAS);
}

// @brief Blocks until a current measurement is completed
// @returns True on success, false otherwise
bool Axis::wait_for_current_meas() {
    if (osSignalWait(M_SIGNAL_PH_CURRENT_MEAS, PH_CURRENT_MEAS_TIMEOUT).status != osEventSignal)
        return error_ = ERROR_CURRENT_MEASUREMENT_TIMEOUT, false;
    return true;
}

static void step_cb_wrapper(void* ctx) {
    reinterpret_cast<Axis*>(ctx)->step_cb();
}

// step/direction interface
void Axis::step_cb() {
    if (enable_step_dir_) {
        GPIO_PinState dir_pin = HAL_GPIO_ReadPin(hw_config_.dir_port, hw_config_.dir_pin);
        float dir = (dir_pin == GPIO_PIN_SET) ? 1.0f : -1.0f;
        controller_.pos_setpoint_ += dir * config_.counts_per_step;
    }
};

// @brief Enables or disables step/dir input
void Axis::set_step_dir_enabled(bool enable) {
    if (enable) {
        // Set up the direction GPIO as input
        GPIO_InitTypeDef GPIO_InitStruct;
        GPIO_InitStruct.Pin = hw_config_.dir_pin;
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        HAL_GPIO_Init(hw_config_.dir_port, &GPIO_InitStruct);

        // Subscribe to rising edges of the step GPIO
        GPIO_subscribe(hw_config_.step_port, hw_config_.step_pin, GPIO_PULLDOWN,
                step_cb_wrapper, this);

        enable_step_dir_ = true;
    } else {
        enable_step_dir_ = false;

        // Unsubscribe from step GPIO
        GPIO_unsubscribe(hw_config_.step_port, hw_config_.step_pin);
    }
}

// @brief Returns true if the power supply is within range
bool Axis::check_PSU_brownout() {
    if(vbus_voltage < config_.dc_bus_brownout_trip_level)
        return error_ = ERROR_BAD_VOLTAGE, false;
    return true;
}

// @brief Returns true if everything is ok.
// Sets error and returns false otherwise.
bool Axis::do_checks() {
    if (!motor_.do_checks())
        return error_ = ERROR_MOTOR_FAILED, false;
    if (!check_PSU_brownout())
        return error_ = ERROR_BAD_VOLTAGE, false;
    return true;
}

bool Axis::run_sensorless_spin_up() {
    // Early Spin-up: spiral up current
    float x = 0.0f;
    run_control_loop([&](){
        float phase = wrap_pm_pi(config_.ramp_up_distance * x);
        float I_mag = config_.spin_up_current * x;
        x += current_meas_period / config_.ramp_up_time;
        if (!motor_.update(I_mag, phase))
            return error_ = ERROR_MOTOR_FAILED, false;
        return x < 1.0f;
    });
    if (error_ != ERROR_NO_ERROR)
        return false;

    // Late Spin-up: accelerate
    float vel = config_.ramp_up_distance / config_.ramp_up_time;
    float phase = wrap_pm_pi(config_.ramp_up_distance);
    run_control_loop([&](){
        vel += config_.spin_up_acceleration * current_meas_period;
        phase = wrap_pm_pi(phase + vel * current_meas_period);
        float I_mag = config_.spin_up_current;
        if (!motor_.update(I_mag, phase))
            return error_ = ERROR_MOTOR_FAILED, false;
        return vel < config_.spin_up_target_vel;
    });
    return error_ == ERROR_NO_ERROR;
}

// Note run_sensorless_control_loop and run_closed_loop_control_loop are very similar and differ only in where we get the estimate from.
bool Axis::run_sensorless_control_loop() {
    set_step_dir_enabled(config_.enable_step_dir);
    run_control_loop([this](){
        float pos_estimate, vel_estimate, phase, current_setpoint;

        if (controller_.config_.control_mode >= CTRL_MODE_POSITION_CONTROL)
            return error_ = ERROR_POS_CTRL_DURING_SENSORLESS, false;

        // We update the encoder just in case someone needs the output for testing
        encoder_.update(nullptr, nullptr, nullptr);
        if (!sensorless_estimator_.update(&pos_estimate, &vel_estimate, &phase))
            return error_ = ERROR_SENSORLESS_ESTIMATOR_FAILED, false;
        if (!controller_.update(pos_estimate, vel_estimate, &current_setpoint))
            return error_ = ERROR_CONTROLLER_FAILED, false;
        if (!motor_.update(current_setpoint, phase))
            return error_ = ERROR_MOTOR_FAILED, false;
        return true;
    });
    set_step_dir_enabled(false);
    return error_ == ERROR_NO_ERROR;
}

bool Axis::run_closed_loop_control_loop() {
    set_step_dir_enabled(config_.enable_step_dir);
    run_control_loop([this](){
        float pos_estimate, vel_estimate, phase, current_setpoint;

        // We update the sensorless estimator just in case someone needs the output for testing
        sensorless_estimator_.update(nullptr, nullptr, nullptr);
        if (!encoder_.update(&pos_estimate, &vel_estimate, &phase))
            return error_ = ERROR_ENCODER_FAILED, false;
        if (!controller_.update(pos_estimate, vel_estimate, &current_setpoint))
            return error_ = ERROR_CONTROLLER_FAILED, false;
        if (!motor_.update(current_setpoint, phase))
            return error_ = ERROR_MOTOR_FAILED, false;
        return true;
    });
    set_step_dir_enabled(false);
    return error_ == ERROR_NO_ERROR;
}

bool Axis::run_idle_loop() {
    // run_control_loop ignores missed modulation timing updates
    // if and only if we're in AXIS_STATE_IDLE
    run_control_loop([this](){
        sensorless_estimator_.update(nullptr, nullptr, nullptr);
        encoder_.update(nullptr, nullptr, nullptr);
        return true;
    });
    return error_ == ERROR_NO_ERROR;
}

// Infinite loop that does calibration and enters main control loop as appropriate
void Axis::run_state_machine_loop() {

    // Allocate the map for anti-cogging algorithm and initialize all values to 0.0f
    // TODO: Move this somewhere else
    // TODO: respect changes of CPR
    int encoder_cpr = encoder_.config_.cpr;
    controller_.anticogging_.cogging_map = (float*)malloc(encoder_cpr * sizeof(float));
    if (controller_.anticogging_.cogging_map != NULL) {
        for (int i = 0; i < encoder_cpr; i++) {
            controller_.anticogging_.cogging_map[i] = 0.0f;
        }
    }

    // arm!
    motor_.arm();

    for (;;) {
        // Load the task chain if a specific request is pending
        if (requested_state_ != AXIS_STATE_UNDEFINED) {
            size_t pos = 0;
            if (requested_state_ == AXIS_STATE_STARTUP_SEQUENCE) {
                if (config_.startup_motor_calibration)
                    task_chain_[pos++] = AXIS_STATE_MOTOR_CALIBRATION;
                if (config_.startup_encoder_calibration)
                    task_chain_[pos++] = AXIS_STATE_ENCODER_CALIBRATION;
                if (config_.startup_closed_loop_control)
                    task_chain_[pos++] = AXIS_STATE_CLOSED_LOOP_CONTROL;
                else if (config_.startup_sensorless_control)
                    task_chain_[pos++] = AXIS_STATE_SENSORLESS_CONTROL;
                task_chain_[pos++] = AXIS_STATE_IDLE;
            } else if (requested_state_ == AXIS_STATE_FULL_CALIBRATION_SEQUENCE) {
                task_chain_[pos++] = AXIS_STATE_MOTOR_CALIBRATION;
                task_chain_[pos++] = AXIS_STATE_ENCODER_CALIBRATION;
                task_chain_[pos++] = AXIS_STATE_IDLE;
            } else if (requested_state_ != AXIS_STATE_UNDEFINED) {
                task_chain_[pos++] = requested_state_;
                task_chain_[pos++] = AXIS_STATE_IDLE;
            }
            task_chain_[pos++] = AXIS_STATE_UNDEFINED;
            // TODO: bounds checking
            requested_state_ = AXIS_STATE_UNDEFINED;
        }

        // Note that current_state is a reference to task_chain_[0]

        // Validate the state before running it
        if (current_state_ > AXIS_STATE_MOTOR_CALIBRATION && !motor_.is_calibrated_)
            current_state_ = AXIS_STATE_UNDEFINED;
        if (current_state_ > AXIS_STATE_ENCODER_CALIBRATION && !encoder_.is_calibrated_)
            current_state_ = AXIS_STATE_UNDEFINED;

        // Run the specified state
        // Handlers should exit if requested_state != AXIS_STATE_UNDEFINED
        bool status;
        switch (current_state_) {
        case AXIS_STATE_MOTOR_CALIBRATION:
            status = motor_.run_calibration();
            break;

        case AXIS_STATE_ENCODER_CALIBRATION:
            status = encoder_.run_calibration();
            break;

        case AXIS_STATE_SENSORLESS_CONTROL:
            status = run_sensorless_spin_up(); // TODO: restart if desired
            if (status)
                status = run_sensorless_control_loop();
            break;

        case AXIS_STATE_CLOSED_LOOP_CONTROL:
            status = run_closed_loop_control_loop();
            break;

        case AXIS_STATE_IDLE:
            run_idle_loop();
            status = motor_.arm(); // done with idling - try to arm the motor
            break;

        default:
            error_ = ERROR_INVALID_STATE;
            status = false; // this will set the state to idle
            break;
        }

        // If the state failed, go to idle, else advance task chain
        if (!status)
            current_state_ = AXIS_STATE_IDLE;
        else
            memcpy(task_chain_, task_chain_ + 1, sizeof(task_chain_) - sizeof(task_chain_[0]));
    }

    thread_id_valid_ = false;
}
<|endoftext|>


<commit_before>// Copyright 2015 Project Vogue. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string>

#include "elang/compiler/testing/analyzer_test.h"

#include "base/strings/utf_string_conversions.h"
#include "elang/compiler/analysis/analysis_editor.h"
#include "elang/compiler/analysis/name_tree_builder.h"
#include "elang/compiler/ast/nodes.h"
#include "elang/compiler/compilation_session.h"
#include "elang/compiler/semantics/nodes.h"

namespace elang {
namespace compiler {

//////////////////////////////////////////////////////////////////////
//
// NameTreeBuilderTest
//
class NameTreeBuilderTest : public testing::AnalyzerTest {
 protected:
  NameTreeBuilderTest() = default;
  ~NameTreeBuilderTest() override = default;

  std::string BuildNameTree();
  sm::Semantic* SemanticOf(base::StringPiece16 path) const;
  sm::Semantic* SemanticOf(base::StringPiece path) const;

 private:
  DISALLOW_COPY_AND_ASSIGN(NameTreeBuilderTest);
};

std::string NameTreeBuilderTest::BuildNameTree() {
  if (!Parse())
    return GetErrors();
  AnalysisEditor editor(session()->analysis());
  NameTreeBuilder(session(), &editor).Run();
  return GetErrors();
}

sm::Semantic* NameTreeBuilderTest::SemanticOf(base::StringPiece16 path) const {
  sm::Semantic* enclosing = session()->semantics_factory()->global_namespace();
  sm::Semantic* found = static_cast<sm::Semantic*>(nullptr);
  for (size_t pos = 0u; pos < path.length(); ++pos) {
    auto dot_pos = path.find('.', pos);
    if (dot_pos == base::StringPiece::npos)
      dot_pos = path.length();
    auto const name =
        session()->NewAtomicString(path.substr(pos, dot_pos - pos));
    found = enclosing->FindMember(name);
    if (!found)
      return nullptr;
    pos = dot_pos;
    if (pos == path.length())
      break;
    enclosing = found;
    if (!enclosing)
      return nullptr;
  }
  return found;
}

sm::Semantic* NameTreeBuilderTest::SemanticOf(base::StringPiece path) const {
  return SemanticOf(base::UTF8ToUTF16(path));
}

TEST_F(NameTreeBuilderTest, AliasConflict) {
  Prepare(
      "namespace N1 { using A = N1; }"
      "namespace N1 { class A{} }");
  EXPECT_EQ("NameResolution.Alias.Conflict(21) A A\n", BuildNameTree());
}

TEST_F(NameTreeBuilderTest, AliasErrorDuplicate) {
  Prepare("namespace N1 { using A = N1; using A = N2; }");
  EXPECT_EQ("Syntax.UsingDirective.Duplicate(35) A A\n", BuildNameTree())
      << "Alias name must be unique in namespace.";
}

TEST_F(NameTreeBuilderTest, ClassBasic) {
  Prepare("class A {} class B{}");
  EXPECT_EQ("", BuildNameTree());
  EXPECT_EQ("#A", ToString(SemanticOf("A")));
  EXPECT_EQ("#B", ToString(SemanticOf("B")));
}

TEST_F(NameTreeBuilderTest, ClassBasicPartial) {
  Prepare("partial class A {}");
  Prepare("partial class A {}");
  EXPECT_EQ("", BuildNameTree());
  EXPECT_EQ("#A", ToString(SemanticOf("A")));
}

TEST_F(NameTreeBuilderTest, ClassErrorConflict) {
  Prepare("class A {}");
  Prepare("namespace A {}");
  EXPECT_EQ("Syntax.Namespace.Conflict(10) A class\n", BuildNameTree());
}

TEST_F(NameTreeBuilderTest, ClassErrorDuplicate) {
  Prepare("class A {}");
  Prepare("class A {}");
  EXPECT_EQ("Syntax.Class.Duplicate(6) A A\n", BuildNameTree());
}

TEST_F(NameTreeBuilderTest, ClassErrorDuplicate2) {
  Prepare("namespace System { class Object {} }");
  EXPECT_EQ("Syntax.Class.Duplicate(25) Object Object\n", BuildNameTree());
}

TEST_F(NameTreeBuilderTest, ConstBasic) {
  Prepare("class A { const int B = 2; }");
  EXPECT_EQ("", BuildNameTree());
  EXPECT_EQ("const ? A.B = ?", ToString(SemanticOf("A.B")));
}

TEST_F(NameTreeBuilderTest, ConstErrorConflict) {
  Prepare("partial class A { const int B = 2; }");
  Prepare("partial class A { int B; }");
  EXPECT_EQ("NameResolution.Field.Conflict(22) B B\n", BuildNameTree());
}

TEST_F(NameTreeBuilderTest, ConstErrorDuplicate) {
  Prepare("partial class A { const int B = 2; }");
  Prepare("partial class A { const int B = 2; }");
  EXPECT_EQ("NameResolution.Const.Duplicate(28) B B\n", BuildNameTree());
}

TEST_F(NameTreeBuilderTest, EnumBasic) {
  Prepare("enum Color { Red, Green, Blue }");
  EXPECT_EQ("", BuildNameTree());
  EXPECT_EQ("#enum Color", ToString(SemanticOf("Color")));
}

TEST_F(NameTreeBuilderTest, EnumErrorConflict) {
  Prepare("enum Color { Red }");
  Prepare("class Color {}");
  EXPECT_EQ("Syntax.Class.Conflict(6) Color Color\n", BuildNameTree());
}

TEST_F(NameTreeBuilderTest, EnumErrorDuplicate) {
  Prepare("enum Color { Red }");
  Prepare("enum Color { Blue }");
  EXPECT_EQ("Syntax.Enum.Duplicate(5) Color Color\n", BuildNameTree());
}

TEST_F(NameTreeBuilderTest, FieldBasic) {
  Prepare("class A { int B = 2; }");
  EXPECT_EQ("", BuildNameTree());
  EXPECT_EQ("A.B", ToString(SemanticOf("A.B")));
}

TEST_F(NameTreeBuilderTest, FieldErrorConflict) {
  Prepare("partial class A { void B() {} }");
  Prepare("partial class A { int B; }");
  EXPECT_EQ("NameResolution.Field.Conflict(22) B B\n", BuildNameTree());
}

TEST_F(NameTreeBuilderTest, FieldErrorDuplicate) {
  Prepare("partial class A { int B = 2; }");
  Prepare("partial class A { int B = 2; }");
  EXPECT_EQ("NameResolution.Field.Duplicate(22) B B\n", BuildNameTree());
}

TEST_F(NameTreeBuilderTest, MethodBasic) {
  Prepare("class A { void B() {} }");
  EXPECT_EQ("", BuildNameTree());
  EXPECT_EQ("#A.B{}", ToString(SemanticOf("A.B")));
}

TEST_F(NameTreeBuilderTest, MethodErrorConflict) {
  Prepare("partial class A { int B; }");
  Prepare("partial class A { void B() {} }");
  EXPECT_EQ("Syntax.ClassMember.Conflict(23) B B\n", BuildNameTree());
}

TEST_F(NameTreeBuilderTest, MethodErrorDuplicate) {
  Prepare("partial class A { void B() {} }");
  Prepare("partial class A { void B() {} }");
  // Since |NameTreeBuilder| doesn't check method signatures, we don't have
  // errors.
  EXPECT_EQ("", BuildNameTree());
}

}  // namespace compiler
}  // namespace elang
<commit_msg>elang/compiler/analysis: Add a test case to |NameTreeBuilderTest|.<commit_after>// Copyright 2015 Project Vogue. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string>

#include "elang/compiler/testing/analyzer_test.h"

#include "base/strings/utf_string_conversions.h"
#include "elang/compiler/analysis/analysis_editor.h"
#include "elang/compiler/analysis/name_tree_builder.h"
#include "elang/compiler/ast/nodes.h"
#include "elang/compiler/compilation_session.h"
#include "elang/compiler/semantics/nodes.h"

namespace elang {
namespace compiler {

//////////////////////////////////////////////////////////////////////
//
// NameTreeBuilderTest
//
class NameTreeBuilderTest : public testing::AnalyzerTest {
 protected:
  NameTreeBuilderTest() = default;
  ~NameTreeBuilderTest() override = default;

  std::string BuildNameTree();
  sm::Semantic* SemanticOf(base::StringPiece16 path) const;
  sm::Semantic* SemanticOf(base::StringPiece path) const;

 private:
  DISALLOW_COPY_AND_ASSIGN(NameTreeBuilderTest);
};

std::string NameTreeBuilderTest::BuildNameTree() {
  if (!Parse())
    return GetErrors();
  AnalysisEditor editor(session()->analysis());
  NameTreeBuilder(session(), &editor).Run();
  return GetErrors();
}

sm::Semantic* NameTreeBuilderTest::SemanticOf(base::StringPiece16 path) const {
  sm::Semantic* enclosing = session()->semantics_factory()->global_namespace();
  sm::Semantic* found = static_cast<sm::Semantic*>(nullptr);
  for (size_t pos = 0u; pos < path.length(); ++pos) {
    auto dot_pos = path.find('.', pos);
    if (dot_pos == base::StringPiece::npos)
      dot_pos = path.length();
    auto const name =
        session()->NewAtomicString(path.substr(pos, dot_pos - pos));
    found = enclosing->FindMember(name);
    if (!found)
      return nullptr;
    pos = dot_pos;
    if (pos == path.length())
      break;
    enclosing = found;
    if (!enclosing)
      return nullptr;
  }
  return found;
}

sm::Semantic* NameTreeBuilderTest::SemanticOf(base::StringPiece path) const {
  return SemanticOf(base::UTF8ToUTF16(path));
}

// Note: MS C# compiler doesn't report error if alias A isn't used.
TEST_F(NameTreeBuilderTest, AliasErrorAmbiguous) {
  Prepare(
      "namespace N1.N2 { class A {} }"
      "namespace N3 { class A {} }"
      "namespace N3 {"
      "  using A = N1.N2.A;"
      "  class B : A {}"  // A can be N1.N2.A or N3.A.
      "}");
  EXPECT_EQ("NameResolution.Alias.Conflict(79) A A\n", BuildNameTree());
}

TEST_F(NameTreeBuilderTest, AliasConflict) {
  Prepare(
      "namespace N1 { using A = N1; }"
      "namespace N1 { class A {} }");
  EXPECT_EQ("NameResolution.Alias.Conflict(21) A A\n", BuildNameTree());
}

TEST_F(NameTreeBuilderTest, AliasErrorDuplicate) {
  Prepare("namespace N1 { using A = N1; using A = N2; }");
  EXPECT_EQ("Syntax.UsingDirective.Duplicate(35) A A\n", BuildNameTree())
      << "Alias name must be unique in namespace.";
}

TEST_F(NameTreeBuilderTest, ClassBasic) {
  Prepare("class A {} class B{}");
  EXPECT_EQ("", BuildNameTree());
  EXPECT_EQ("#A", ToString(SemanticOf("A")));
  EXPECT_EQ("#B", ToString(SemanticOf("B")));
}

TEST_F(NameTreeBuilderTest, ClassBasicPartial) {
  Prepare("partial class A {}");
  Prepare("partial class A {}");
  EXPECT_EQ("", BuildNameTree());
  EXPECT_EQ("#A", ToString(SemanticOf("A")));
}

TEST_F(NameTreeBuilderTest, ClassErrorConflict) {
  Prepare("class A {}");
  Prepare("namespace A {}");
  EXPECT_EQ("Syntax.Namespace.Conflict(10) A class\n", BuildNameTree());
}

TEST_F(NameTreeBuilderTest, ClassErrorDuplicate) {
  Prepare("class A {}");
  Prepare("class A {}");
  EXPECT_EQ("Syntax.Class.Duplicate(6) A A\n", BuildNameTree());
}

TEST_F(NameTreeBuilderTest, ClassErrorDuplicate2) {
  Prepare("namespace System { class Object {} }");
  EXPECT_EQ("Syntax.Class.Duplicate(25) Object Object\n", BuildNameTree());
}

TEST_F(NameTreeBuilderTest, ConstBasic) {
  Prepare("class A { const int B = 2; }");
  EXPECT_EQ("", BuildNameTree());
  EXPECT_EQ("const ? A.B = ?", ToString(SemanticOf("A.B")));
}

TEST_F(NameTreeBuilderTest, ConstErrorConflict) {
  Prepare("partial class A { const int B = 2; }");
  Prepare("partial class A { int B; }");
  EXPECT_EQ("NameResolution.Field.Conflict(22) B B\n", BuildNameTree());
}

TEST_F(NameTreeBuilderTest, ConstErrorDuplicate) {
  Prepare("partial class A { const int B = 2; }");
  Prepare("partial class A { const int B = 2; }");
  EXPECT_EQ("NameResolution.Const.Duplicate(28) B B\n", BuildNameTree());
}

TEST_F(NameTreeBuilderTest, EnumBasic) {
  Prepare("enum Color { Red, Green, Blue }");
  EXPECT_EQ("", BuildNameTree());
  EXPECT_EQ("#enum Color", ToString(SemanticOf("Color")));
}

TEST_F(NameTreeBuilderTest, EnumErrorConflict) {
  Prepare("enum Color { Red }");
  Prepare("class Color {}");
  EXPECT_EQ("Syntax.Class.Conflict(6) Color Color\n", BuildNameTree());
}

TEST_F(NameTreeBuilderTest, EnumErrorDuplicate) {
  Prepare("enum Color { Red }");
  Prepare("enum Color { Blue }");
  EXPECT_EQ("Syntax.Enum.Duplicate(5) Color Color\n", BuildNameTree());
}

TEST_F(NameTreeBuilderTest, FieldBasic) {
  Prepare("class A { int B = 2; }");
  EXPECT_EQ("", BuildNameTree());
  EXPECT_EQ("A.B", ToString(SemanticOf("A.B")));
}

TEST_F(NameTreeBuilderTest, FieldErrorConflict) {
  Prepare("partial class A { void B() {} }");
  Prepare("partial class A { int B; }");
  EXPECT_EQ("NameResolution.Field.Conflict(22) B B\n", BuildNameTree());
}

TEST_F(NameTreeBuilderTest, FieldErrorDuplicate) {
  Prepare("partial class A { int B = 2; }");
  Prepare("partial class A { int B = 2; }");
  EXPECT_EQ("NameResolution.Field.Duplicate(22) B B\n", BuildNameTree());
}

TEST_F(NameTreeBuilderTest, MethodBasic) {
  Prepare("class A { void B() {} }");
  EXPECT_EQ("", BuildNameTree());
  EXPECT_EQ("#A.B{}", ToString(SemanticOf("A.B")));
}

TEST_F(NameTreeBuilderTest, MethodErrorConflict) {
  Prepare("partial class A { int B; }");
  Prepare("partial class A { void B() {} }");
  EXPECT_EQ("Syntax.ClassMember.Conflict(23) B B\n", BuildNameTree());
}

TEST_F(NameTreeBuilderTest, MethodErrorDuplicate) {
  Prepare("partial class A { void B() {} }");
  Prepare("partial class A { void B() {} }");
  // Since |NameTreeBuilder| doesn't check method signatures, we don't have
  // errors.
  EXPECT_EQ("", BuildNameTree());
}

}  // namespace compiler
}  // namespace elang
<|endoftext|>


<commit_before>template <typename T>
class Tree {
	struct Node {
		Node *left = nullptr;
		Node *right = nullptr;
		T value;
	};

	Node *root;

	Node *& find(Node *& n, const T &value) {
		if(!n || n->value == value) {
			return n;
		}

		if (value > n->value) {
			return find(n->right, value);
		} else {
			return find(n->left, value);
		}
	}

public:
	Tree(): root(nullptr) {}

	void insert(const T &value) {
		Node *& n = find(root, value);
		n->value = value;
	}

	bool find(const T&value) {
		return find(root, value) != nullptr;
	}

	bool remove(const T&value) {
		Node *& n = find(root, value);
		if (!n) {
			return false;
		}

		if (!n->left && !n->right) {
			delete n;
			n = nullptr;
		} else if (n->left) {
			Node *del = n;
			n = n->left;
			delete del;
		} else if (n->right) {
			Node *del = n;
			n = n->right;
			delete del;
		} else {

		}
	}
};

int main() {
	int *p;
	alloc(p, 100);
}<commit_msg>Delete one more unrelated source<commit_after><|endoftext|>


<commit_before>// Copyright 2014 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 "ash/wm/maximize_mode/maximize_mode_window_state.h"

#include "ash/display/display_controller.h"
#include "ash/screen_util.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "ash/wm/coordinate_conversion.h"
#include "ash/wm/maximize_mode/maximize_mode_window_manager.h"
#include "ash/wm/window_animations.h"
#include "ash/wm/window_state.h"
#include "ash/wm/window_state_delegate.h"
#include "ash/wm/window_state_util.h"
#include "ash/wm/window_util.h"
#include "ash/wm/wm_event.h"
#include "ash/wm/workspace/workspace_window_resizer.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
#include "ui/gfx/display.h"
#include "ui/gfx/rect.h"

namespace ash {
namespace {

// Returns the biggest possible size for a window which is about to be
// maximized.
gfx::Size GetMaximumSizeOfWindow(wm::WindowState* window_state) {
  DCHECK(window_state->CanMaximize() || window_state->CanResize());

  gfx::Size workspace_size = ScreenUtil::GetMaximizedWindowBoundsInParent(
      window_state->window()).size();

  aura::WindowDelegate* delegate = window_state->window()->delegate();
  if (!delegate)
    return workspace_size;

  gfx::Size size = delegate->GetMaximumSize();
  if (size.IsEmpty())
    return workspace_size;

  size.SetToMin(workspace_size);
  return size;
}

// Returns the centered bounds of the given bounds in the work area.
gfx::Rect GetCenteredBounds(const gfx::Rect& bounds_in_parent,
                            wm::WindowState* state_object) {
  gfx::Rect work_area_in_parent =
      ScreenUtil::GetDisplayWorkAreaBoundsInParent(state_object->window());
  work_area_in_parent.ClampToCenteredSize(bounds_in_parent.size());
  return work_area_in_parent;
}

// Returns the maximized/full screen and/or centered bounds of a window.
gfx::Rect GetBoundsInMaximizedMode(wm::WindowState* state_object) {
  if (state_object->IsFullscreen())
    return ScreenUtil::GetDisplayBoundsInParent(state_object->window());

  gfx::Rect bounds_in_parent;
  // Make the window as big as possible.
  if (state_object->CanMaximize() || state_object->CanResize()) {
    bounds_in_parent.set_size(GetMaximumSizeOfWindow(state_object));
  } else {
    // We prefer the user given window dimensions over the current windows
    // dimensions since they are likely to be the result from some other state
    // object logic.
    if (state_object->HasRestoreBounds())
      bounds_in_parent = state_object->GetRestoreBoundsInParent();
    else
      bounds_in_parent = state_object->window()->bounds();
  }
  return GetCenteredBounds(bounds_in_parent, state_object);
}

}  // namespace

// static
void MaximizeModeWindowState::UpdateWindowPosition(
    wm::WindowState* window_state, bool animated) {
  gfx::Rect bounds_in_parent = GetBoundsInMaximizedMode(window_state);

  if (bounds_in_parent == window_state->window()->bounds())
    return;

  if (animated)
    window_state->SetBoundsDirect(bounds_in_parent);
  else
    window_state->SetBoundsDirectAnimated(bounds_in_parent);
}

MaximizeModeWindowState::MaximizeModeWindowState(
    aura::Window* window, MaximizeModeWindowManager* creator)
    : window_(window),
      creator_(creator),
      current_state_type_(wm::GetWindowState(window)->GetStateType()) {
  old_state_.reset(
      wm::GetWindowState(window)->SetStateObject(
          scoped_ptr<State>(this).Pass()).release());
}

MaximizeModeWindowState::~MaximizeModeWindowState() {
  creator_->WindowStateDestroyed(window_);
}

void MaximizeModeWindowState::LeaveMaximizeMode(wm::WindowState* window_state) {
  // Note: When we return we will destroy ourselves with the |our_reference|.
  scoped_ptr<wm::WindowState::State> our_reference =
      window_state->SetStateObject(old_state_.Pass());
}

void MaximizeModeWindowState::OnWMEvent(wm::WindowState* window_state,
                                        const wm::WMEvent* event) {
  switch (event->type()) {
    case wm::WM_EVENT_TOGGLE_FULLSCREEN:
      ToggleFullScreen(window_state, window_state->delegate());
      break;
    case wm::WM_EVENT_FULLSCREEN:
      UpdateWindow(window_state, wm::WINDOW_STATE_TYPE_FULLSCREEN, true);
      break;
    case wm::WM_EVENT_TOGGLE_MAXIMIZE_CAPTION:
    case wm::WM_EVENT_TOGGLE_VERTICAL_MAXIMIZE:
    case wm::WM_EVENT_TOGGLE_HORIZONTAL_MAXIMIZE:
    case wm::WM_EVENT_TOGGLE_MAXIMIZE:
    case wm::WM_EVENT_CENTER:
    case wm::WM_EVENT_SNAP_LEFT:
    case wm::WM_EVENT_SNAP_RIGHT:
    case wm::WM_EVENT_NORMAL:
    case wm::WM_EVENT_MAXIMIZE:
      UpdateWindow(window_state,
                   GetMaximizedOrCenteredWindowType(window_state),
                   true);
      return;
    case wm::WM_EVENT_MINIMIZE:
      UpdateWindow(window_state, wm::WINDOW_STATE_TYPE_MINIMIZED, true);
      return;
    case wm::WM_EVENT_SHOW_INACTIVE:
      return;
    case wm::WM_EVENT_SET_BOUNDS:
      if (window_state->CanResize()) {
        // In case the window is resizable and / or maximized we ignore the
        // requested bounds change and resize to the biggest possible size.
        UpdateBounds(window_state, true);
      } else
      if (current_state_type_ != wm::WINDOW_STATE_TYPE_MINIMIZED &&
          current_state_type_ != wm::WINDOW_STATE_TYPE_MAXIMIZED) {
        // In all other cases (except for minimized windows) we respect the
        // requested bounds and center it to a fully visible area on the screen.
        gfx::Rect bounds_in_parent =
            (static_cast<const wm::SetBoundsEvent*>(event))->requested_bounds();
        bounds_in_parent = GetCenteredBounds(bounds_in_parent, window_state);
        if (bounds_in_parent != window_state->window()->bounds()) {
          if (window_state->window()->IsVisible())
            window_state->SetBoundsDirectAnimated(bounds_in_parent);
          else
            window_state->SetBoundsDirect(bounds_in_parent);
        }
      }
      break;
    case wm::WM_EVENT_ADDED_TO_WORKSPACE:
      if (current_state_type_ != wm::WINDOW_STATE_TYPE_MAXIMIZED &&
          current_state_type_ != wm::WINDOW_STATE_TYPE_FULLSCREEN &&
          current_state_type_ != wm::WINDOW_STATE_TYPE_MINIMIZED) {
        wm::WindowStateType new_state =
            GetMaximizedOrCenteredWindowType(window_state);
        UpdateWindow(window_state, new_state, true);
      }
      break;
    case wm::WM_EVENT_WORKAREA_BOUNDS_CHANGED:
    case wm::WM_EVENT_DISPLAY_BOUNDS_CHANGED:
      if (current_state_type_ != wm::WINDOW_STATE_TYPE_MINIMIZED)
        UpdateBounds(window_state, true);
      break;
  }
}

wm::WindowStateType MaximizeModeWindowState::GetType() const {
  return current_state_type_;
}

void MaximizeModeWindowState::AttachState(
    wm::WindowState* window_state,
    wm::WindowState::State* previous_state) {
  current_state_type_ = previous_state->GetType();

  // Initialize the state to a good preset.
  if (current_state_type_ != wm::WINDOW_STATE_TYPE_MAXIMIZED &&
      current_state_type_ != wm::WINDOW_STATE_TYPE_MINIMIZED &&
      current_state_type_ != wm::WINDOW_STATE_TYPE_FULLSCREEN) {
    UpdateWindow(window_state,
                 GetMaximizedOrCenteredWindowType(window_state),
                 true);
  }

  window_state->set_can_be_dragged(false);
}

void MaximizeModeWindowState::DetachState(wm::WindowState* window_state) {
  window_state->set_can_be_dragged(true);
}

void MaximizeModeWindowState::UpdateWindow(wm::WindowState* window_state,
                                           wm::WindowStateType target_state,
                                           bool animated) {
  DCHECK(target_state == wm::WINDOW_STATE_TYPE_MINIMIZED ||
         target_state == wm::WINDOW_STATE_TYPE_MAXIMIZED ||
         (target_state == wm::WINDOW_STATE_TYPE_NORMAL &&
              !window_state->CanMaximize()) ||
         target_state == wm::WINDOW_STATE_TYPE_FULLSCREEN);

  if (target_state == wm::WINDOW_STATE_TYPE_MINIMIZED) {
    if (current_state_type_ == wm::WINDOW_STATE_TYPE_MINIMIZED)
      return;

    current_state_type_ = target_state;
    ::wm::SetWindowVisibilityAnimationType(
        window_state->window(), WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE);
    window_state->window()->Hide();
    if (window_state->IsActive())
      window_state->Deactivate();
    return;
  }

  if (current_state_type_ == target_state) {
    // If the state type did not change, update it accordingly.
    UpdateBounds(window_state, animated);
    return;
  }

  const wm::WindowStateType old_state_type = current_state_type_;
  current_state_type_ = target_state;
  window_state->UpdateWindowShowStateFromStateType();
  window_state->NotifyPreStateTypeChange(old_state_type);
  UpdateBounds(window_state, animated);
  window_state->NotifyPostStateTypeChange(old_state_type);

  if ((window_state->window()->TargetVisibility() ||
      old_state_type == wm::WINDOW_STATE_TYPE_MINIMIZED) &&
      !window_state->window()->layer()->visible()) {
    // The layer may be hidden if the window was previously minimized. Make
    // sure it's visible.
    window_state->window()->Show();
  }
}

wm::WindowStateType MaximizeModeWindowState::GetMaximizedOrCenteredWindowType(
      wm::WindowState* window_state) {
  return window_state->CanMaximize() ? wm::WINDOW_STATE_TYPE_MAXIMIZED :
                                       wm::WINDOW_STATE_TYPE_NORMAL;
}

void MaximizeModeWindowState::UpdateBounds(wm::WindowState* window_state,
                                           bool animated) {
  gfx::Rect bounds_in_parent = GetBoundsInMaximizedMode(window_state);
  // If we have a target bounds rectangle, we center it and set it
  // accordingly.
  if (!bounds_in_parent.IsEmpty() &&
      bounds_in_parent != window_state->window()->bounds()) {
    if (current_state_type_ == wm::WINDOW_STATE_TYPE_MINIMIZED ||
        !window_state->window()->IsVisible() ||
        !animated) {
      window_state->SetBoundsDirect(bounds_in_parent);
    } else {
      window_state->SetBoundsDirectAnimated(bounds_in_parent);
    }
  }
}

}  // namespace ash
<commit_msg>Fixing "black flash" when going into maximized mode.<commit_after>// Copyright 2014 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 "ash/wm/maximize_mode/maximize_mode_window_state.h"

#include "ash/display/display_controller.h"
#include "ash/screen_util.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "ash/wm/coordinate_conversion.h"
#include "ash/wm/maximize_mode/maximize_mode_window_manager.h"
#include "ash/wm/window_animations.h"
#include "ash/wm/window_state.h"
#include "ash/wm/window_state_delegate.h"
#include "ash/wm/window_state_util.h"
#include "ash/wm/window_util.h"
#include "ash/wm/wm_event.h"
#include "ash/wm/workspace/workspace_window_resizer.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
#include "ui/gfx/display.h"
#include "ui/gfx/rect.h"

namespace ash {
namespace {

// Returns the biggest possible size for a window which is about to be
// maximized.
gfx::Size GetMaximumSizeOfWindow(wm::WindowState* window_state) {
  DCHECK(window_state->CanMaximize() || window_state->CanResize());

  gfx::Size workspace_size = ScreenUtil::GetMaximizedWindowBoundsInParent(
      window_state->window()).size();

  aura::WindowDelegate* delegate = window_state->window()->delegate();
  if (!delegate)
    return workspace_size;

  gfx::Size size = delegate->GetMaximumSize();
  if (size.IsEmpty())
    return workspace_size;

  size.SetToMin(workspace_size);
  return size;
}

// Returns the centered bounds of the given bounds in the work area.
gfx::Rect GetCenteredBounds(const gfx::Rect& bounds_in_parent,
                            wm::WindowState* state_object) {
  gfx::Rect work_area_in_parent =
      ScreenUtil::GetDisplayWorkAreaBoundsInParent(state_object->window());
  work_area_in_parent.ClampToCenteredSize(bounds_in_parent.size());
  return work_area_in_parent;
}

// Returns the maximized/full screen and/or centered bounds of a window.
gfx::Rect GetBoundsInMaximizedMode(wm::WindowState* state_object) {
  if (state_object->IsFullscreen())
    return ScreenUtil::GetDisplayBoundsInParent(state_object->window());

  gfx::Rect bounds_in_parent;
  // Make the window as big as possible.
  if (state_object->CanMaximize() || state_object->CanResize()) {
    bounds_in_parent.set_size(GetMaximumSizeOfWindow(state_object));
  } else {
    // We prefer the user given window dimensions over the current windows
    // dimensions since they are likely to be the result from some other state
    // object logic.
    if (state_object->HasRestoreBounds())
      bounds_in_parent = state_object->GetRestoreBoundsInParent();
    else
      bounds_in_parent = state_object->window()->bounds();
  }
  return GetCenteredBounds(bounds_in_parent, state_object);
}

}  // namespace

// static
void MaximizeModeWindowState::UpdateWindowPosition(
    wm::WindowState* window_state, bool animated) {
  gfx::Rect bounds_in_parent = GetBoundsInMaximizedMode(window_state);

  if (bounds_in_parent == window_state->window()->bounds())
    return;

  if (animated)
    window_state->SetBoundsDirect(bounds_in_parent);
  else
    window_state->SetBoundsDirectAnimated(bounds_in_parent);
}

MaximizeModeWindowState::MaximizeModeWindowState(
    aura::Window* window, MaximizeModeWindowManager* creator)
    : window_(window),
      creator_(creator),
      current_state_type_(wm::GetWindowState(window)->GetStateType()) {
  old_state_.reset(
      wm::GetWindowState(window)->SetStateObject(
          scoped_ptr<State>(this).Pass()).release());
}

MaximizeModeWindowState::~MaximizeModeWindowState() {
  creator_->WindowStateDestroyed(window_);
}

void MaximizeModeWindowState::LeaveMaximizeMode(wm::WindowState* window_state) {
  // Note: When we return we will destroy ourselves with the |our_reference|.
  scoped_ptr<wm::WindowState::State> our_reference =
      window_state->SetStateObject(old_state_.Pass());
}

void MaximizeModeWindowState::OnWMEvent(wm::WindowState* window_state,
                                        const wm::WMEvent* event) {
  switch (event->type()) {
    case wm::WM_EVENT_TOGGLE_FULLSCREEN:
      ToggleFullScreen(window_state, window_state->delegate());
      break;
    case wm::WM_EVENT_FULLSCREEN:
      UpdateWindow(window_state, wm::WINDOW_STATE_TYPE_FULLSCREEN, true);
      break;
    case wm::WM_EVENT_TOGGLE_MAXIMIZE_CAPTION:
    case wm::WM_EVENT_TOGGLE_VERTICAL_MAXIMIZE:
    case wm::WM_EVENT_TOGGLE_HORIZONTAL_MAXIMIZE:
    case wm::WM_EVENT_TOGGLE_MAXIMIZE:
    case wm::WM_EVENT_CENTER:
    case wm::WM_EVENT_SNAP_LEFT:
    case wm::WM_EVENT_SNAP_RIGHT:
    case wm::WM_EVENT_NORMAL:
    case wm::WM_EVENT_MAXIMIZE:
      UpdateWindow(window_state,
                   GetMaximizedOrCenteredWindowType(window_state),
                   true);
      return;
    case wm::WM_EVENT_MINIMIZE:
      UpdateWindow(window_state, wm::WINDOW_STATE_TYPE_MINIMIZED, true);
      return;
    case wm::WM_EVENT_SHOW_INACTIVE:
      return;
    case wm::WM_EVENT_SET_BOUNDS:
      if (window_state->CanResize()) {
        // In case the window is resizable and / or maximized we ignore the
        // requested bounds change and resize to the biggest possible size.
        UpdateBounds(window_state, true);
      } else
      if (current_state_type_ != wm::WINDOW_STATE_TYPE_MINIMIZED &&
          current_state_type_ != wm::WINDOW_STATE_TYPE_MAXIMIZED) {
        // In all other cases (except for minimized windows) we respect the
        // requested bounds and center it to a fully visible area on the screen.
        gfx::Rect bounds_in_parent =
            (static_cast<const wm::SetBoundsEvent*>(event))->requested_bounds();
        bounds_in_parent = GetCenteredBounds(bounds_in_parent, window_state);
        if (bounds_in_parent != window_state->window()->bounds()) {
          if (window_state->window()->IsVisible())
            window_state->SetBoundsDirectAnimated(bounds_in_parent);
          else
            window_state->SetBoundsDirect(bounds_in_parent);
        }
      }
      break;
    case wm::WM_EVENT_ADDED_TO_WORKSPACE:
      if (current_state_type_ != wm::WINDOW_STATE_TYPE_MAXIMIZED &&
          current_state_type_ != wm::WINDOW_STATE_TYPE_FULLSCREEN &&
          current_state_type_ != wm::WINDOW_STATE_TYPE_MINIMIZED) {
        wm::WindowStateType new_state =
            GetMaximizedOrCenteredWindowType(window_state);
        UpdateWindow(window_state, new_state, true);
      }
      break;
    case wm::WM_EVENT_WORKAREA_BOUNDS_CHANGED:
    case wm::WM_EVENT_DISPLAY_BOUNDS_CHANGED:
      if (current_state_type_ != wm::WINDOW_STATE_TYPE_MINIMIZED)
        UpdateBounds(window_state, true);
      break;
  }
}

wm::WindowStateType MaximizeModeWindowState::GetType() const {
  return current_state_type_;
}

void MaximizeModeWindowState::AttachState(
    wm::WindowState* window_state,
    wm::WindowState::State* previous_state) {
  current_state_type_ = previous_state->GetType();

  // Initialize the state to a good preset.
  if (current_state_type_ != wm::WINDOW_STATE_TYPE_MAXIMIZED &&
      current_state_type_ != wm::WINDOW_STATE_TYPE_MINIMIZED &&
      current_state_type_ != wm::WINDOW_STATE_TYPE_FULLSCREEN) {
    UpdateWindow(window_state,
                 GetMaximizedOrCenteredWindowType(window_state),
                 true);
  }

  window_state->set_can_be_dragged(false);
}

void MaximizeModeWindowState::DetachState(wm::WindowState* window_state) {
  window_state->set_can_be_dragged(true);
}

void MaximizeModeWindowState::UpdateWindow(wm::WindowState* window_state,
                                           wm::WindowStateType target_state,
                                           bool animated) {
  DCHECK(target_state == wm::WINDOW_STATE_TYPE_MINIMIZED ||
         target_state == wm::WINDOW_STATE_TYPE_MAXIMIZED ||
         (target_state == wm::WINDOW_STATE_TYPE_NORMAL &&
              !window_state->CanMaximize()) ||
         target_state == wm::WINDOW_STATE_TYPE_FULLSCREEN);

  if (target_state == wm::WINDOW_STATE_TYPE_MINIMIZED) {
    if (current_state_type_ == wm::WINDOW_STATE_TYPE_MINIMIZED)
      return;

    current_state_type_ = target_state;
    ::wm::SetWindowVisibilityAnimationType(
        window_state->window(), WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE);
    window_state->window()->Hide();
    if (window_state->IsActive())
      window_state->Deactivate();
    return;
  }

  if (current_state_type_ == target_state) {
    // If the state type did not change, update it accordingly.
    UpdateBounds(window_state, animated);
    return;
  }

  const wm::WindowStateType old_state_type = current_state_type_;
  current_state_type_ = target_state;
  window_state->UpdateWindowShowStateFromStateType();
  window_state->NotifyPreStateTypeChange(old_state_type);
  UpdateBounds(window_state, animated);
  window_state->NotifyPostStateTypeChange(old_state_type);

  if ((window_state->window()->TargetVisibility() ||
      old_state_type == wm::WINDOW_STATE_TYPE_MINIMIZED) &&
      !window_state->window()->layer()->visible()) {
    // The layer may be hidden if the window was previously minimized. Make
    // sure it's visible.
    window_state->window()->Show();
  }
}

wm::WindowStateType MaximizeModeWindowState::GetMaximizedOrCenteredWindowType(
      wm::WindowState* window_state) {
  return window_state->CanMaximize() ? wm::WINDOW_STATE_TYPE_MAXIMIZED :
                                       wm::WINDOW_STATE_TYPE_NORMAL;
}

void MaximizeModeWindowState::UpdateBounds(wm::WindowState* window_state,
                                           bool animated) {
  gfx::Rect bounds_in_parent = GetBoundsInMaximizedMode(window_state);
  // If we have a target bounds rectangle, we center it and set it
  // accordingly.
  if (!bounds_in_parent.IsEmpty() &&
      bounds_in_parent != window_state->window()->bounds()) {
    if (current_state_type_ == wm::WINDOW_STATE_TYPE_MINIMIZED ||
        !window_state->window()->IsVisible() ||
        !animated) {
      window_state->SetBoundsDirect(bounds_in_parent);
    } else {
      // If we animate (to) maximized mode, we want to use the cross fade to
      // avoid flashing.
      if (window_state->IsMaximized())
        window_state->SetBoundsDirectCrossFade(bounds_in_parent);
      else
        window_state->SetBoundsDirectAnimated(bounds_in_parent);
    }
  }
}

}  // namespace ash
<|endoftext|>


<commit_before>#include <stdio.h>
#include  "bochs.h"

class bx_ioapic_c bx_ioapic;
#define LOG_THIS  bx_ioapic.

void
bx_io_redirect_entry_t::parse_value ()
{
  dest = (value >> 56) & 0xff;
  masked = (value >> 16) & 1;
  trig_mode = (value >> 15) & 1;
  remote_irr = (value >> 14) & 1;
  polarity = (value >> 13) & 1;
  //delivery_status = (value >> 12) & 1;
  delivery_status = 0;  // always say the message has gone through
  dest_mode = (value >> 11) & 1;
  delivery_mode = (value >> 8) & 7;
  vector = (value >> 0) & 0xff;
}

void
bx_io_redirect_entry_t::sprintf_self (char *buf)
{
  sprintf (buf, "dest=%02x, masked=%d, trig_mode=%d, remote_irr=%d, polarity=%d, delivery_status=%d, dest_mode=%d, delivery_mode=%d, vector=%02x", dest, masked, trig_mode, remote_irr, polarity, delivery_status, dest_mode, delivery_mode, vector);
}

bx_ioapic_c::bx_ioapic_c ()
  : bx_generic_apic_c ()
{
}

bx_ioapic_c::~bx_ioapic_c () {
}

void
bx_ioapic_c::init ()
{
  bx_generic_apic_c::init ();
  if (bx_dbg.ioapic)
    BX_INFO(("initializing I/O APIC\n"));
  base_addr = 0xfec00000;
  ioregsel = 0;
  // all interrupts masked
  for (int i=0; i<BX_IOAPIC_NUM_PINS; i++) {
    ioredtbl[i].set_even_word (0x00010000);
    ioredtbl[i].set_odd_word  (0x00000000);
  }
  irr = 0;
}

void
bx_ioapic_c::read_aligned(Bit32u address, Bit32u *data, unsigned len)
{
  if (bx_dbg.ioapic)
    BX_INFO( ("I/O APIC read_aligned addr=%08x, len=%d\n", address, len));
  BX_ASSERT (len == 4);
  address &= 0xff;
  if (address == 0x00) {
    // select register
    *data = ioregsel;
    return;
  } else if (address != 0x10) {
      BX_PANIC(("IOAPIC: read from unsupported address\n"));
  }
  // only reached when reading data register
  switch (ioregsel) {
  case 0x00:  // APIC ID
    *data = ((id & 0xf) << 24);
    return;
  case 0x01:  // version
    *data = (((BX_IOAPIC_NUM_PINS-1) & 0xff) << 16)
            | (BX_IOAPIC_VERSION_ID & 0x0f);
    return;
  case 0x02:
    BX_INFO(("IOAPIC: arbitration ID unsupported, returned 0\n"));
    *data = 0;
    return;
  default:
    int index = (ioregsel - 0x10) >> 1;
    if (index >= 0 && index < BX_IOAPIC_NUM_PINS) {
      bx_io_redirect_entry_t *entry = ioredtbl + index;
      *data = (ioregsel&1) ? entry->get_odd_word() : entry->get_even_word ();
      return;
    }
    BX_PANIC(("IOAPIC: IOREGSEL points to undefined register %02x\n", ioregsel));
  }
}

void
bx_ioapic_c::write(Bit32u address, Bit32u *value, unsigned len)
{
  if (bx_dbg.ioapic)
    BX_INFO(("IOAPIC: write addr=%08x, data=%08x, len=%d\n", address, *value, len));
  address &= 0xff;
  if (address == 0x00)  {
    ioregsel = *value;
    return;
  } else if (address != 0x10) {
    BX_PANIC(("IOAPIC: write to unsupported address\n"));
  }
  // only reached when writing data register
  switch (ioregsel) {
    case 0x00: // set APIC ID
      {
	Bit8u newid = (*value >> 24) & 0xf;
	BX_INFO(("IOAPIC: setting id to 0x%x\n", newid));
	set_id (newid);
	return;
      }
    case 0x01: // version
    case 0x02: // arbitration id
      BX_INFO(("IOAPIC: could not write, IOREGSEL=0x%02x\n", ioregsel));
      return;
    default:
      int index = (ioregsel - 0x10) >> 1;
      if (index >= 0 && index < BX_IOAPIC_NUM_PINS) {
	bx_io_redirect_entry_t *entry = ioredtbl + index;
	if (ioregsel&1)
	  entry->set_odd_word (*value);
	else
	  entry->set_even_word (*value);
	char buf[1024];
	entry->sprintf_self (buf);
        if (bx_dbg.ioapic)
	  BX_INFO(("IOAPIC: now entry[%d] is %s\n", index, buf));
	service_ioapic ();
	return;
      }
      BX_PANIC(("IOAPIC: IOREGSEL points to undefined register %02x\n", ioregsel));
  }
}

void bx_ioapic_c::trigger_irq (unsigned vector, unsigned from)
{
  if (bx_dbg.ioapic)
    BX_INFO(("IOAPIC: received interrupt %d\n", vector));
  if (vector >= 0 && vector < BX_IOAPIC_NUM_PINS) {
    Bit32u bit = 1<<vector;
    if ((irr & bit) == 0) {
      irr |= bit;
      service_ioapic ();
    }
  } else BX_PANIC(("IOAPIC: vector %d out of range\n", vector));
}

void bx_ioapic_c::untrigger_irq (unsigned num, unsigned from)
{
  if (bx_dbg.ioapic)
    BX_INFO(("IOAPIC: interrupt %d went away\n", num));
}

void bx_ioapic_c::service_ioapic ()
{
  // look in IRR and deliver any interrupts that are not masked.
  if (bx_dbg.ioapic)
    BX_INFO(("IOAPIC: servicing\n"));
  for (unsigned bit=0; bit < BX_IOAPIC_NUM_PINS; bit++) {
    if (irr & (1<<bit)) {
      bx_io_redirect_entry_t *entry = ioredtbl + bit;
      if (!entry->masked) {
	// clear irr bit and deliver
	Boolean done = deliver (entry->dest, entry->dest_mode, entry->delivery_mode, entry->vector, entry->polarity, entry->trig_mode);
	if (done) irr &= ~(1<<bit);
      }
    }
  }
}
<commit_msg>- set prefix using new I/O code<commit_after>#include <stdio.h>
#include  "bochs.h"

class bx_ioapic_c bx_ioapic;
#define LOG_THIS  bx_ioapic.

void
bx_io_redirect_entry_t::parse_value ()
{
  dest = (value >> 56) & 0xff;
  masked = (value >> 16) & 1;
  trig_mode = (value >> 15) & 1;
  remote_irr = (value >> 14) & 1;
  polarity = (value >> 13) & 1;
  //delivery_status = (value >> 12) & 1;
  delivery_status = 0;  // always say the message has gone through
  dest_mode = (value >> 11) & 1;
  delivery_mode = (value >> 8) & 7;
  vector = (value >> 0) & 0xff;
}

void
bx_io_redirect_entry_t::sprintf_self (char *buf)
{
  sprintf (buf, "dest=%02x, masked=%d, trig_mode=%d, remote_irr=%d, polarity=%d, delivery_status=%d, dest_mode=%d, delivery_mode=%d, vector=%02x", dest, masked, trig_mode, remote_irr, polarity, delivery_status, dest_mode, delivery_mode, vector);
}

bx_ioapic_c::bx_ioapic_c ()
  : bx_generic_apic_c ()
{
  setprefix("[IOAP]");
  settype(IOAPICLOG);
}

bx_ioapic_c::~bx_ioapic_c () {
}

void
bx_ioapic_c::init ()
{
  bx_generic_apic_c::init ();
  if (bx_dbg.ioapic)
    BX_INFO(("initializing I/O APIC\n"));
  base_addr = 0xfec00000;
  ioregsel = 0;
  // all interrupts masked
  for (int i=0; i<BX_IOAPIC_NUM_PINS; i++) {
    ioredtbl[i].set_even_word (0x00010000);
    ioredtbl[i].set_odd_word  (0x00000000);
  }
  irr = 0;
}

void
bx_ioapic_c::read_aligned(Bit32u address, Bit32u *data, unsigned len)
{
  if (bx_dbg.ioapic)
    BX_INFO( ("I/O APIC read_aligned addr=%08x, len=%d\n", address, len));
  BX_ASSERT (len == 4);
  address &= 0xff;
  if (address == 0x00) {
    // select register
    *data = ioregsel;
    return;
  } else if (address != 0x10) {
      BX_PANIC(("IOAPIC: read from unsupported address\n"));
  }
  // only reached when reading data register
  switch (ioregsel) {
  case 0x00:  // APIC ID
    *data = ((id & 0xf) << 24);
    return;
  case 0x01:  // version
    *data = (((BX_IOAPIC_NUM_PINS-1) & 0xff) << 16)
            | (BX_IOAPIC_VERSION_ID & 0x0f);
    return;
  case 0x02:
    BX_INFO(("IOAPIC: arbitration ID unsupported, returned 0\n"));
    *data = 0;
    return;
  default:
    int index = (ioregsel - 0x10) >> 1;
    if (index >= 0 && index < BX_IOAPIC_NUM_PINS) {
      bx_io_redirect_entry_t *entry = ioredtbl + index;
      *data = (ioregsel&1) ? entry->get_odd_word() : entry->get_even_word ();
      return;
    }
    BX_PANIC(("IOAPIC: IOREGSEL points to undefined register %02x\n", ioregsel));
  }
}

void
bx_ioapic_c::write(Bit32u address, Bit32u *value, unsigned len)
{
  if (bx_dbg.ioapic)
    BX_INFO(("IOAPIC: write addr=%08x, data=%08x, len=%d\n", address, *value, len));
  address &= 0xff;
  if (address == 0x00)  {
    ioregsel = *value;
    return;
  } else if (address != 0x10) {
    BX_PANIC(("IOAPIC: write to unsupported address\n"));
  }
  // only reached when writing data register
  switch (ioregsel) {
    case 0x00: // set APIC ID
      {
	Bit8u newid = (*value >> 24) & 0xf;
	BX_INFO(("IOAPIC: setting id to 0x%x\n", newid));
	set_id (newid);
	return;
      }
    case 0x01: // version
    case 0x02: // arbitration id
      BX_INFO(("IOAPIC: could not write, IOREGSEL=0x%02x\n", ioregsel));
      return;
    default:
      int index = (ioregsel - 0x10) >> 1;
      if (index >= 0 && index < BX_IOAPIC_NUM_PINS) {
	bx_io_redirect_entry_t *entry = ioredtbl + index;
	if (ioregsel&1)
	  entry->set_odd_word (*value);
	else
	  entry->set_even_word (*value);
	char buf[1024];
	entry->sprintf_self (buf);
        if (bx_dbg.ioapic)
	  BX_INFO(("IOAPIC: now entry[%d] is %s\n", index, buf));
	service_ioapic ();
	return;
      }
      BX_PANIC(("IOAPIC: IOREGSEL points to undefined register %02x\n", ioregsel));
  }
}

void bx_ioapic_c::trigger_irq (unsigned vector, unsigned from)
{
  if (bx_dbg.ioapic)
    BX_INFO(("IOAPIC: received interrupt %d\n", vector));
  if (vector >= 0 && vector < BX_IOAPIC_NUM_PINS) {
    Bit32u bit = 1<<vector;
    if ((irr & bit) == 0) {
      irr |= bit;
      service_ioapic ();
    }
  } else BX_PANIC(("IOAPIC: vector %d out of range\n", vector));
}

void bx_ioapic_c::untrigger_irq (unsigned num, unsigned from)
{
  if (bx_dbg.ioapic)
    BX_INFO(("IOAPIC: interrupt %d went away\n", num));
}

void bx_ioapic_c::service_ioapic ()
{
  // look in IRR and deliver any interrupts that are not masked.
  if (bx_dbg.ioapic)
    BX_INFO(("IOAPIC: servicing\n"));
  for (unsigned bit=0; bit < BX_IOAPIC_NUM_PINS; bit++) {
    if (irr & (1<<bit)) {
      bx_io_redirect_entry_t *entry = ioredtbl + bit;
      if (!entry->masked) {
	// clear irr bit and deliver
	Boolean done = deliver (entry->dest, entry->dest_mode, entry->delivery_mode, entry->vector, entry->polarity, entry->trig_mode);
	if (done) irr &= ~(1<<bit);
      }
    }
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2011-2013 Blender Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

#include "device.h"
#include "scene.h"
#include "tables.h"

#include "util_debug.h"

CCL_NAMESPACE_BEGIN

/* Lookup Tables */

LookupTables::LookupTables()
{
	need_update = true;
}

LookupTables::~LookupTables()
{
	assert(lookup_tables.size() == 0);
}

void LookupTables::device_update(Device *device, DeviceScene *dscene)
{
	if(!need_update)
		return;

	device->tex_alloc("__lookup_table", dscene->lookup_table);

	need_update = false;
}

void LookupTables::device_free(Device *device, DeviceScene *dscene)
{
	device->tex_free(dscene->lookup_table);
	dscene->lookup_table.clear();
}

static size_t round_up_to_multiple(size_t size, size_t chunk)
{
	return ((size + chunk - 1)/chunk) * chunk;
}

size_t LookupTables::add_table(DeviceScene *dscene, vector<float>& data)
{
	assert(data.size() > 0);

	need_update = true;

	Table new_table;
	new_table.offset = 0;
	new_table.size = round_up_to_multiple(data.size(), TABLE_CHUNK_SIZE);

	/* find space to put lookup table */
	list<Table>::iterator table;

	for(table = lookup_tables.begin(); table != lookup_tables.end(); table++) {
		if(new_table.offset + new_table.size <= table->offset) {
			lookup_tables.insert(table, new_table);
			break;
		}
		else
			new_table.offset = table->offset + table->size;
	}

	if(table == lookup_tables.end()) {
		/* add at the end */
		lookup_tables.push_back(new_table);
		dscene->lookup_table.resize(new_table.offset + new_table.size);
	}

	/* copy table data and return offset */
	dscene->lookup_table.copy_at(&data[0], new_table.offset, data.size());
	return new_table.offset;
}

void LookupTables::remove_table(size_t offset)
{
	need_update = true;

	list<Table>::iterator table;

	for(table = lookup_tables.begin(); table != lookup_tables.end(); table++) {
		if(table->offset == offset) {
			lookup_tables.erase(table);
			return;
		}
	}

	assert(table != lookup_tables.end());
}

CCL_NAMESPACE_END

<commit_msg>Fix T39146: recent cycles CUDA regression in fix for T39114.<commit_after>/*
 * Copyright 2011-2013 Blender Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

#include "device.h"
#include "scene.h"
#include "tables.h"

#include "util_debug.h"

CCL_NAMESPACE_BEGIN

/* Lookup Tables */

LookupTables::LookupTables()
{
	need_update = true;
}

LookupTables::~LookupTables()
{
	assert(lookup_tables.size() == 0);
}

void LookupTables::device_update(Device *device, DeviceScene *dscene)
{
	if(!need_update)
		return;

	device->tex_free(dscene->lookup_table);

	if(lookup_tables.size() > 0)
		device->tex_alloc("__lookup_table", dscene->lookup_table);

	need_update = false;
}

void LookupTables::device_free(Device *device, DeviceScene *dscene)
{
	device->tex_free(dscene->lookup_table);
	dscene->lookup_table.clear();
}

static size_t round_up_to_multiple(size_t size, size_t chunk)
{
	return ((size + chunk - 1)/chunk) * chunk;
}

size_t LookupTables::add_table(DeviceScene *dscene, vector<float>& data)
{
	assert(data.size() > 0);

	need_update = true;

	Table new_table;
	new_table.offset = 0;
	new_table.size = round_up_to_multiple(data.size(), TABLE_CHUNK_SIZE);

	/* find space to put lookup table */
	list<Table>::iterator table;

	for(table = lookup_tables.begin(); table != lookup_tables.end(); table++) {
		if(new_table.offset + new_table.size <= table->offset) {
			lookup_tables.insert(table, new_table);
			break;
		}
		else
			new_table.offset = table->offset + table->size;
	}

	if(table == lookup_tables.end()) {
		/* add at the end */
		lookup_tables.push_back(new_table);
		dscene->lookup_table.resize(new_table.offset + new_table.size);
	}

	/* copy table data and return offset */
	dscene->lookup_table.copy_at(&data[0], new_table.offset, data.size());
	return new_table.offset;
}

void LookupTables::remove_table(size_t offset)
{
	need_update = true;

	list<Table>::iterator table;

	for(table = lookup_tables.begin(); table != lookup_tables.end(); table++) {
		if(table->offset == offset) {
			lookup_tables.erase(table);
			return;
		}
	}

	assert(table != lookup_tables.end());
}

CCL_NAMESPACE_END

<|endoftext|>


<commit_before>#include "cinder/app/App.h"
#include "cinder/app/RendererGl.h"
#include "cinder/gl/gl.h"

#include "GridMesh.h"
#include "cinder/MotionManager.h"

using namespace ci;
using namespace ci::app;
using namespace std;

using namespace soso;

class GridSpaceApp : public App {
public:
	void setup() override;
	void mouseDown( MouseEvent event ) override;
	void update() override;
	void draw() override;
private:
	GridMesh				mesh;
	CameraPersp			camera;
	const ci::vec3	target = vec3( 50, 5, 50 );
};

void GridSpaceApp::setup()
{
	mesh.setup();
	MotionManager::enable();

	camera.lookAt( vec3( 0 ), target, vec3( 0, 1, 0 ) );
	camera.setPerspective( 60, getWindowAspectRatio(), 0.1f, 1000 );
}

void GridSpaceApp::mouseDown( MouseEvent event )
{
}

void GridSpaceApp::update()
{
	if( MotionManager::isDataAvailable() ) {
		auto r = MotionManager::getRotation();
		camera.setOrientation( r );
	}
}

void GridSpaceApp::draw()
{
	gl::clear( Color( 0, 0, 0 ) );
	gl::enableDepthRead();
	gl::enableDepthWrite();

	gl::setMatrices( camera );
	mesh.draw();

	gl::setMatricesWindowPersp( getWindowSize() );
	gl::translate( vec3( getWindowCenter(), 0 ) );
	gl::rotate( MotionManager::getRotation() );
	gl::drawCube( vec3( 0 ), vec3( 50, 100, 5 ) );

	gl::scale( vec3( 50 ) );
	gl::drawCoordinateFrame();
}

CINDER_APP( GridSpaceApp, RendererGl )
<commit_msg>Remove rectangle.<commit_after>#include "cinder/app/App.h"
#include "cinder/app/RendererGl.h"
#include "cinder/gl/gl.h"

#include "GridMesh.h"
#include "cinder/MotionManager.h"

using namespace ci;
using namespace ci::app;
using namespace std;

using namespace soso;

class GridSpaceApp : public App {
public:
	void setup() override;
	void mouseDown( MouseEvent event ) override;
	void update() override;
	void draw() override;
private:
	GridMesh				mesh;
	CameraPersp			camera;
	const ci::vec3	target = vec3( 50, 5, 50 );
};

void GridSpaceApp::setup()
{
	mesh.setup();
	MotionManager::enable();

	camera.lookAt( vec3( 0 ), target, vec3( 0, 1, 0 ) );
	camera.setPerspective( 60, getWindowAspectRatio(), 0.1f, 1000 );
}

void GridSpaceApp::mouseDown( MouseEvent event )
{
}

void GridSpaceApp::update()
{
	if( MotionManager::isDataAvailable() ) {
		auto r = MotionManager::getRotation();
		camera.setOrientation( r );
	}
}

void GridSpaceApp::draw()
{
	gl::clear( Color( 0, 0, 0 ) );
	gl::enableDepthRead();
	gl::enableDepthWrite();

	gl::setMatrices( camera );
	mesh.draw();

	/*
	gl::setMatricesWindowPersp( getWindowSize() );
	gl::translate( vec3( getWindowCenter(), 0 ) );
	gl::rotate( MotionManager::getRotation() );
	gl::drawCube( vec3( 0 ), vec3( 50, 100, 5 ) );

	gl::scale( vec3( 50 ) );
	gl::drawCoordinateFrame();
	*/
}

CINDER_APP( GridSpaceApp, RendererGl )
<|endoftext|>


<commit_before>#include "FeedbackMaskInteractor.h"
#include "FeedbackMaskInteractor.moc"

#include "Data/Feature.h"

#include <cmath>

namespace MFE
{
	// ------------------------------------------------------------------------
	void MaskMessenger::EmitUpdated()
	{
		emit Updated();
	}

	// ------------------------------------------------------------------------
	FeedbackMaskInteractor::FeedbackMaskInteractor() : currentFeature(0)
	{
		messenger = new MaskMessenger();
		lastPid = -1;
	}

	// ------------------------------------------------------------------------
	FeedbackMaskInteractor::~FeedbackMaskInteractor()
	{
		delete messenger;
	}

	// ------------------------------------------------------------------------
	void FeedbackMaskInteractor::SetFeature(Feature *feature)
	{
		currentFeature = feature;
	}

	// ------------------------------------------------------------------------
	bool FeedbackMaskInteractor::MouseMoveEvent(NQVTK::MouseEvent event)
	{
		if (currentFeature &&
			(event.buttons & NQVTK::MouseEvent::LeftButton) != 0)
		{
			// Find the property under the cursor
			int pid = static_cast<int>(
				static_cast<double>(event.x * currentFeature->mask.size()) /
				static_cast<double>(viewportWidth));
			// Don't toggle the same property twice
			if (pid != lastPid)
			{
				// Toggle the mask
				currentFeature->mask[pid] = !currentFeature->mask[pid];
			}

			lastPid = pid;

			messenger->EmitUpdated();
			return true;
		}

		return false;
	}

	// ------------------------------------------------------------------------
	bool FeedbackMaskInteractor::MouseReleaseEvent(NQVTK::MouseEvent event)
	{
		// Make sure the button involved in the event is considered active
		event.buttons |= event.button;

		bool res = MouseMoveEvent(event);

		if (event.button == NQVTK::MouseEvent::LeftButton);
		// Allow a next click to toggle any property
		lastPid = -1;

		return res;
	}
}
<commit_msg>Fixed minor typo-bug.<commit_after>#include "FeedbackMaskInteractor.h"
#include "FeedbackMaskInteractor.moc"

#include "Data/Feature.h"

#include <cmath>

namespace MFE
{
	// ------------------------------------------------------------------------
	void MaskMessenger::EmitUpdated()
	{
		emit Updated();
	}

	// ------------------------------------------------------------------------
	FeedbackMaskInteractor::FeedbackMaskInteractor() : currentFeature(0)
	{
		messenger = new MaskMessenger();
		lastPid = -1;
	}

	// ------------------------------------------------------------------------
	FeedbackMaskInteractor::~FeedbackMaskInteractor()
	{
		delete messenger;
	}

	// ------------------------------------------------------------------------
	void FeedbackMaskInteractor::SetFeature(Feature *feature)
	{
		currentFeature = feature;
	}

	// ------------------------------------------------------------------------
	bool FeedbackMaskInteractor::MouseMoveEvent(NQVTK::MouseEvent event)
	{
		if (currentFeature &&
			(event.buttons & NQVTK::MouseEvent::LeftButton) != 0)
		{
			// Find the property under the cursor
			int pid = static_cast<int>(
				static_cast<double>(event.x * currentFeature->mask.size()) /
				static_cast<double>(viewportWidth));
			// Don't toggle the same property twice
			if (pid != lastPid)
			{
				// Toggle the mask
				currentFeature->mask[pid] = !currentFeature->mask[pid];
			}

			lastPid = pid;

			messenger->EmitUpdated();
			return true;
		}

		return false;
	}

	// ------------------------------------------------------------------------
	bool FeedbackMaskInteractor::MouseReleaseEvent(NQVTK::MouseEvent event)
	{
		// Make sure the button involved in the event is considered active
		event.buttons |= event.button;

		bool res = MouseMoveEvent(event);

		if (event.button == NQVTK::MouseEvent::LeftButton)
		{
			// Allow a next click to toggle any property
			lastPid = -1;
		}

		return res;
	}
}
<|endoftext|>