<commit_before>//
// Created by andreanistico on 06/02/17.
//

#include <iostream>
#include "include/Lander/StatesClasses.hpp"
#include "Lander/Lander.h"
#include "parameters.h"

Lander::Lander()
        : _horizontaErr((double)0)    , _tauHold((double)0), _tauLost((double)0), _tauErr((double)0), _NHold(0),
          _NLost(0), _initS(&_machine), _holdS(&_machine)  , _asceS(&_machine)  , _descS(&_machine),_compS(&_machine),
          _err(0,0), _err_int(0,0), _err_diff(0,0), _dt(0), _prevTime(0), _actualTime(0)
{

    initStateMachine();

}

void Lander::setState(MavState pose) {
    _state = pose;
}

MavState Lander::getState() {
    return _state;
}

MavState Lander::getCommand() {
    return _setPoint;
}

void Lander::initStateMachine() {

    //Link signals
    _machine._horizontaErr =  &_horizontaErr;
    _machine._tauErr       =  &_tauErr;
    _machine._tauHold      =  &_tauHold;
    _machine._tauLost      =  &_tauLost;
    _machine._NLost        =  &_NLost;
    _machine._NHold        =  &_NHold;
    _machine._NComp        =  &_NComp;
    _machine._state        =  &_state;
    _machine._setPoint     =  &_setPoint;

    //Link states
    _initS._nextState    = &_holdS;
    _holdS._nextAscState = &_asceS;
    _holdS._nextDesState = &_descS;
    _holdS._nextComState = &_compS;
    _asceS._nextState    = &_holdS;
    _descS._nextState    = &_holdS;
    _compS._nextState    = &_asceS;

    _machine.setStatePtr(&_initS);

    _tauHold = 0.5 * params_automatic::platformLenght;
    _tauLost = params_automatic::platformLenght;

    //Print actual state
    std::cout << "Actual state: " << _machine.getActualNodeId() << std::endl;

}

void Lander::setPlatformState(const MavState platformState) {
    _platformState = platformState;
}

void Lander::updateSignals() {

    int state = _machine.getActualNodeId();
    //Compute horizontal error
    double xTemp = _state.getX();
    double yTemp = _state.getY();
    double xPlatTemp = _platformState.getX();
    double yPlatTemp = _platformState.getY();

    double dx = xPlatTemp - xTemp;
    double dy = yPlatTemp - yTemp;

    _err[0] = dx;
    _err[1] = dy;

    _horizontaErr = _err.norm();

    if( state == AbstractLandState::states::HOLD ||
        state == AbstractLandState::states::ASCE ||
        state == AbstractLandState::states::DESC ||
        state == AbstractLandState::states::COMP){

        //Increment N if needed
        if (_horizontaErr < _tauHold) {
            _NLost = 0;
            _NHold++;
        }
        else if (_horizontaErr > _tauLost) {
            _NHold = 0;
            _NComp = 0;
            _NLost++;
        }
/*
        if(state == AbstractLandState::states::HOLD) {

            if ((fabs(_state.getZ() - (-params_automatic::zMin)) < 0.1) && _horizontaErr < _tauHold) {
                _NComp++;
            } else{
                _NComp = 0;
            }
        }
*/
        if(state == AbstractLandState::states::COMP)  {

            //Check whether we are on place to land
            if (_horizontaErr < _tauHold) {
                _NComp++;
            } else{
                _NComp = 0;
            }

        }

    }

#ifdef DEBUG
    std::cout << "HERRO: " << _horizontaErr<< std::endl;
    std::cout << "NHOLD: " << _NHold<< std::endl;
    std::cout << "NLOST: " << _NLost<< std::endl;

    std::cout << "INTEX: " << _err_int[0] << std::endl;
    std::cout << "INTEY: " << _err_int[1] << std::endl;
#endif

}

void Lander::handleMachine() {
    _machine.handle();
}

int Lander::getActualMachineState() {
    return _machine.getActualNodeId();
}

void Lander::resetSetPoint() {

    _setPoint = _state;
    _setPoint.setType(MavState::type::POSITION);

}

void Lander::hold() {

    //This function is purely tracking, nothing more

    /*
     * The tracking is performed by POSITION control, issuing the position setpoint
     * in order to achieve the desired velocity calculated by:
     *
     * Vdes = K * ep + Vplat
     * or
     * Psp = Pplat + K * Vplat
     *
     * where:
     *
     * Vdes = desired velocity, K = proportional gain, ep = position error, Vplat = paltform velocity
     */

    //Cache values
    MavState platPos = _platformState;
    MavState state   = _state;

    Eigen::Vector2d tempVel(platPos.getVx(),platPos.getVy());
    Eigen::Vector2d tempSetPoint(platPos.getX(),platPos.getY());

    updateIntegrals();
    //PosSP = PlatPos + K * Vplat
    tempSetPoint += params_automatic::KpHold * tempVel + params_automatic::KiHold * _err_int;

    //Fill right fields
    _setPoint.setPosition(tempSetPoint(0),tempSetPoint(1),_setPoint.getZ());
    _setPoint.setType(MavState::POSITION);

}

void Lander::init() {

    //Set point to my position
    resetSetPoint();

    //TODO: improve height logic(we assume that we are safely flying)
    //Go to max tracking height
    _setPoint.setZ(params_automatic::zMax);

}

void Lander::run() {

    managetime();
    int state = getActualMachineState();
    static bool initDone = false;
    switch (state){

        case (AbstractLandState::states::INIT):
            if(!initDone){
                init();
                initDone = true;
            }
            break;

        case (AbstractLandState::states::HOLD):
            initDone = false;
            clampZSP();
            hold();
            break;
        case (AbstractLandState::states::DESC):

            desc();
            clampZSP();
            break;
        case (AbstractLandState::states::ASCE):

            asce();
            clampZSP();
            break;
        case (AbstractLandState::states::COMP):

            comp();
            break;

        default:
            hold();
            break;

    }

}

void Lander::updateIntegrals() {

    _err_int[0] +=  _dt * _err[0];
    _err_int[1] +=  _dt * _err[1];

    double tempx,tempy;

    tempx = common::clamp(_err_int[0],params_automatic::minIntValue,params_automatic::maxIntValue);
    tempy = common::clamp(_err_int[1],params_automatic::minIntValue,params_automatic::maxIntValue);

    _err_int[0] =  tempx;
    _err_int[1] =  tempy;

}

void Lander::managetime() {

    _actualTime = common::time::getTimeMilliSecond();
    double dt = _prevTime != 0 ? (_actualTime - _prevTime) * (double)MILLI2SECS : 0.0;
    _prevTime = _actualTime;
    _dt = dt;

}

void Lander::resetIntegrals() {

    _err_int[0] = 0;
    _err_int[1] = 0;

}

void Lander::asce() {

    resetIntegrals();
    _setPoint.setZ(_setPoint.getZ() + 0.1);

}

void Lander::desc() {

    //Add step because z is negative up
    _setPoint.setZ(_setPoint.getZ() - 0.1);
}

void Lander::comp() {

    hold();

    MavState tempState = _state;
    //Calculate desired vertical velocity in order to compensate oscillations
    double desc = 0.07;
    double z_target_v = _platformState.getVz() - desc;

    double err_v = z_target_v - tempState.getVz();

    double corr = 1;

    if(_platformState.getVz() > 0) corr = 1.1;

    z_target_v += corr * params_automatic::KPComp * (err_v);

    //Now we need to transform this velocity in a position setpoint since in Firmware:
    // VelSP = Kp * PosError then PosSP = ( VelSP / Kp ) + RobotPos

    _setPoint.setZ((z_target_v) + tempState.getZ());

    //_setPoint.setZ(-_platformState.getZ() - 0.6);
}

void Lander::clampZSP() {

    double temp;
    temp = common::clamp(fabs(_setPoint.getZ()),params_automatic::zMin,params_automatic::zMax);

    _setPoint.setZ(temp);
}

<commit_msg>fix style<commit_after>//
// Created by andreanistico on 06/02/17.
//

#include <iostream>
#include "include/Lander/StatesClasses.hpp"
#include "Lander/Lander.h"
#include "parameters.h"

Lander::Lander()
        : _horizontaErr((double)0)    , _tauHold((double)0), _tauLost((double)0), _tauErr((double)0), _NHold(0),
          _NLost(0), _initS(&_machine), _holdS(&_machine)  , _asceS(&_machine)  , _descS(&_machine),_compS(&_machine),
          _err(0,0), _err_int(0,0), _err_diff(0,0), _dt(0), _prevTime(0), _actualTime(0)
{

    initStateMachine();

}

void Lander::setState(MavState pose) {
    _state = pose;
}

MavState Lander::getState() {
    return _state;
}

MavState Lander::getCommand() {
    return _setPoint;
}

void Lander::initStateMachine() {

    //Link signals
    _machine._horizontaErr =  &_horizontaErr;
    _machine._tauErr       =  &_tauErr;
    _machine._tauHold      =  &_tauHold;
    _machine._tauLost      =  &_tauLost;
    _machine._NLost        =  &_NLost;
    _machine._NHold        =  &_NHold;
    _machine._NComp        =  &_NComp;
    _machine._state        =  &_state;
    _machine._setPoint     =  &_setPoint;

    //Link states
    _initS._nextState    = &_holdS;
    _holdS._nextAscState = &_asceS;
    _holdS._nextDesState = &_descS;
    _holdS._nextComState = &_compS;
    _asceS._nextState    = &_holdS;
    _descS._nextState    = &_holdS;
    _compS._nextState    = &_asceS;

    _machine.setStatePtr(&_initS);

    _tauHold = 0.5 * params_automatic::platformLenght;
    _tauLost = params_automatic::platformLenght;

    //Print actual state
    std::cout << "Actual state: " << _machine.getActualNodeId() << std::endl;

}

void Lander::setPlatformState(const MavState platformState) {
    _platformState = platformState;
}

void Lander::updateSignals() {

    int state = _machine.getActualNodeId();
    //Compute horizontal error
    double xTemp = _state.getX();
    double yTemp = _state.getY();
    double xPlatTemp = _platformState.getX();
    double yPlatTemp = _platformState.getY();

    double dx = xPlatTemp - xTemp;
    double dy = yPlatTemp - yTemp;

    _err[0] = dx;
    _err[1] = dy;

    _horizontaErr = _err.norm();

    if( state == AbstractLandState::states::HOLD ||
        state == AbstractLandState::states::ASCE ||
        state == AbstractLandState::states::DESC ||
        state == AbstractLandState::states::COMP){

        //Increment N if needed
        if (_horizontaErr < _tauHold) {
            _NLost = 0;
            _NHold++;
        }
        else if (_horizontaErr > _tauLost) {
            _NHold = 0;
            _NComp = 0;
            _NLost++;
        }
/*
        if(state == AbstractLandState::states::HOLD) {

            if ((fabs(_state.getZ() - (-params_automatic::zMin)) < 0.1) && _horizontaErr < _tauHold) {
                _NComp++;
            } else{
                _NComp = 0;
            }
        }
*/
        if(state == AbstractLandState::states::COMP)  {

            //Check whether we are on place to land
            if (_horizontaErr < _tauHold) {
                _NComp++;
            } else{
                _NComp = 0;
            }
        }
    }

#ifdef DEBUG
    std::cout << "HERRO: " << _horizontaErr<< std::endl;
    std::cout << "NHOLD: " << _NHold<< std::endl;
    std::cout << "NLOST: " << _NLost<< std::endl;

    std::cout << "INTEX: " << _err_int[0] << std::endl;
    std::cout << "INTEY: " << _err_int[1] << std::endl;
#endif

}

void Lander::handleMachine() {
    _machine.handle();
}

int Lander::getActualMachineState() {
    return _machine.getActualNodeId();
}

void Lander::resetSetPoint() {

    _setPoint = _state;
    _setPoint.setType(MavState::type::POSITION);

}

void Lander::hold() {

    //This function is purely tracking, nothing more

    /*
     * The tracking is performed by POSITION control, issuing the position setpoint
     * in order to achieve the desired velocity calculated by:
     *
     * Vdes = K * ep + Vplat
     * or
     * Psp = Pplat + K * Vplat
     *
     * where:
     *
     * Vdes = desired velocity, K = proportional gain, ep = position error, Vplat = paltform velocity
     */

    //Cache values
    MavState platPos = _platformState;
    MavState state   = _state;

    Eigen::Vector2d tempVel(platPos.getVx(),platPos.getVy());
    Eigen::Vector2d tempSetPoint(platPos.getX(),platPos.getY());

    updateIntegrals();
    //PosSP = PlatPos + K * Vplat
    tempSetPoint += params_automatic::KpHold * tempVel + params_automatic::KiHold * _err_int;

    //Fill right fields
    _setPoint.setPosition(tempSetPoint(0),tempSetPoint(1),_setPoint.getZ());
    _setPoint.setType(MavState::POSITION);

}

void Lander::init() {

    //Set point to my position
    resetSetPoint();

    //TODO: improve height logic(we assume that we are safely flying)
    //Go to max tracking height
    _setPoint.setZ(params_automatic::zMax);

}

void Lander::run() {

    managetime();
    int state = getActualMachineState();
    static bool initDone = false;
    switch (state){

        case (AbstractLandState::states::INIT):
            if(!initDone){
                init();
                initDone = true;
            }
            break;

        case (AbstractLandState::states::HOLD):
            initDone = false;
            clampZSP();
            hold();
            break;
        case (AbstractLandState::states::DESC):

            desc();
            clampZSP();
            break;
        case (AbstractLandState::states::ASCE):

            asce();
            clampZSP();
            break;
        case (AbstractLandState::states::COMP):

            comp();
            break;

        default:
            hold();
            break;

    }

}

void Lander::updateIntegrals() {

    _err_int[0] +=  _dt * _err[0];
    _err_int[1] +=  _dt * _err[1];

    double tempx,tempy;

    tempx = common::clamp(_err_int[0],params_automatic::minIntValue,params_automatic::maxIntValue);
    tempy = common::clamp(_err_int[1],params_automatic::minIntValue,params_automatic::maxIntValue);

    _err_int[0] =  tempx;
    _err_int[1] =  tempy;

}

void Lander::managetime() {

    _actualTime = common::time::getTimeMilliSecond();
    double dt = _prevTime != 0 ? (_actualTime - _prevTime) * (double)MILLI2SECS : 0.0;
    _prevTime = _actualTime;
    _dt = dt;

}

void Lander::resetIntegrals() {

    _err_int[0] = 0;
    _err_int[1] = 0;

}

void Lander::asce() {

    resetIntegrals();
    _setPoint.setZ(_setPoint.getZ() + 0.1);

}

void Lander::desc() {

    //Add step because z is negative up
    _setPoint.setZ(_setPoint.getZ() - 0.1);
}

void Lander::comp() {

    hold();

    MavState tempState = _state;
    //Calculate desired vertical velocity in order to compensate oscillations
    double desc = 0.07;
    double z_target_v = _platformState.getVz() - desc;

    double err_v = z_target_v - tempState.getVz();

    double corr = 1;

    if(_platformState.getVz() > 0) corr = 1.1;

    z_target_v += corr * params_automatic::KPComp * (err_v);

    //Now we need to transform this velocity in a position setpoint since in Firmware:
    // VelSP = Kp * PosError then PosSP = ( VelSP / Kp ) + RobotPos

    _setPoint.setZ((z_target_v) + tempState.getZ());

    //_setPoint.setZ(-_platformState.getZ() - 0.6);
}

void Lander::clampZSP() {

    double temp;
    temp = common::clamp(fabs(_setPoint.getZ()),params_automatic::zMin,params_automatic::zMax);

    _setPoint.setZ(temp);
}

<|endoftext|>


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

#include "base/command_line.h"
#include "base/file_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/path_service.h"
#include "base/test/trace_event_analyzer.h"
#include "base/version.h"
#include "chrome/browser/gpu_blacklist.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/test_launcher_utils.h"
#include "chrome/test/base/tracing.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/gpu_data_manager.h"
#include "content/public/common/content_switches.h"
#include "net/base/net_util.h"
#include "ui/gfx/gl/gl_switches.h"

using content::GpuDataManager;
using content::GpuFeatureType;

namespace {

typedef uint32 GpuResultFlags;
#define EXPECT_NO_GPU_PROCESS         GpuResultFlags(1<<0)
// Expect a SwapBuffers to occur (see gles2_cmd_decoder.cc).
#define EXPECT_GPU_SWAP_BUFFERS       GpuResultFlags(1<<1)

class GpuFeatureTest : public InProcessBrowserTest {
 public:
  GpuFeatureTest() {}

  virtual void SetUpInProcessBrowserTestFixture() {
    FilePath test_dir;
    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
    gpu_test_dir_ = test_dir.AppendASCII("gpu");
  }

  virtual void SetUpCommandLine(CommandLine* command_line) {
    // This enables DOM automation for tab contents.
    EnableDOMAutomation();

    InProcessBrowserTest::SetUpCommandLine(command_line);

    // Do not use mesa if real GPU is required.
    if (!command_line->HasSwitch("use-gpu-in-tests")) {
#if !defined(OS_MACOSX)
      CHECK(test_launcher_utils::OverrideGLImplementation(
          command_line, gfx::kGLImplementationOSMesaName)) <<
          "kUseGL must not be set by test framework code!";
#endif
    }
    command_line->AppendSwitch(switches::kDisablePopupBlocking);
    command_line->AppendSwitchASCII(switches::kWindowSize, "400,300");
  }

  void SetupBlacklist(const std::string& json_blacklist) {
    GpuBlacklist* blacklist = GpuBlacklist::GetInstance();
    ASSERT_TRUE(blacklist->LoadGpuBlacklist(
        "1.0", json_blacklist, GpuBlacklist::kAllOs));
    blacklist->UpdateGpuDataManager();
  }

  // If expected_reply is NULL, we don't check the reply content.
  void RunTest(const FilePath& url,
               const char* expected_reply,
               bool new_tab) {
    FilePath test_path;
    test_path = gpu_test_dir_.Append(url);
    ASSERT_TRUE(file_util::PathExists(test_path))
        << "Missing test file: " << test_path.value();

    ui_test_utils::DOMMessageQueue message_queue;
    if (new_tab) {
      ui_test_utils::NavigateToURLWithDisposition(
          browser(), net::FilePathToFileURL(test_path),
          NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_NONE);
    } else {
      ui_test_utils::NavigateToURL(
          browser(), net::FilePathToFileURL(test_path));
    }

    std::string result;
    // Wait for message indicating the test has finished running.
    ASSERT_TRUE(message_queue.WaitForMessage(&result));
    if (expected_reply)
      EXPECT_STREQ(expected_reply, result.c_str());
  }

  void RunTest(const FilePath& url, GpuResultFlags expectations) {
    using trace_analyzer::Query;
    using trace_analyzer::TraceAnalyzer;

    ASSERT_TRUE(tracing::BeginTracing("test_gpu"));

    // Have to use a new tab for the blacklist to work.
    RunTest(url, NULL, true);

    std::string json_events;
    ASSERT_TRUE(tracing::EndTracing(&json_events));

    scoped_ptr<TraceAnalyzer> analyzer(TraceAnalyzer::Create(json_events));
    analyzer->AssociateBeginEndEvents();
    trace_analyzer::TraceEventVector events;

    // This measurement is flaky, because the GPU process is sometimes
    // started before the test (always with force-compositing-mode on CrOS).
    if (expectations & EXPECT_NO_GPU_PROCESS) {
      EXPECT_EQ(0u, analyzer->FindEvents(
          Query::MatchBeginName("OnGraphicsInfoCollected"), &events));
    }

    // Check for swap buffers if expected:
    if (expectations & EXPECT_GPU_SWAP_BUFFERS) {
      EXPECT_GT(analyzer->FindEvents(Query::EventName() ==
                                     Query::String("SwapBuffers"), &events),
                size_t(0));
    }
  }

 protected:
  FilePath gpu_test_dir_;
};

IN_PROC_BROWSER_TEST_F(GpuFeatureTest, AcceleratedCompositingAllowed) {
  GpuFeatureType type = GpuDataManager::GetInstance()->GetGpuFeatureType();
  EXPECT_EQ(type, 0);

  const FilePath url(FILE_PATH_LITERAL("feature_compositing.html"));
  RunTest(url, EXPECT_GPU_SWAP_BUFFERS);
}

IN_PROC_BROWSER_TEST_F(GpuFeatureTest, AcceleratedCompositingBlocked) {
  const std::string json_blacklist =
      "{\n"
      "  \"name\": \"gpu blacklist\",\n"
      "  \"version\": \"1.0\",\n"
      "  \"entries\": [\n"
      "    {\n"
      "      \"id\": 1,\n"
      "      \"blacklist\": [\n"
      "        \"accelerated_compositing\"\n"
      "      ]\n"
      "    }\n"
      "  ]\n"
      "}";
  SetupBlacklist(json_blacklist);
  GpuFeatureType type = GpuDataManager::GetInstance()->GetGpuFeatureType();
  EXPECT_EQ(type, content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING);

  const FilePath url(FILE_PATH_LITERAL("feature_compositing.html"));
  RunTest(url, EXPECT_NO_GPU_PROCESS);
}

class AcceleratedCompositingTest : public GpuFeatureTest {
 public:
  virtual void SetUpCommandLine(CommandLine* command_line) {
    GpuFeatureTest::SetUpCommandLine(command_line);
    command_line->AppendSwitch(switches::kDisableAcceleratedCompositing);
  }
};

IN_PROC_BROWSER_TEST_F(AcceleratedCompositingTest,
                       AcceleratedCompositingDisabled) {
  const FilePath url(FILE_PATH_LITERAL("feature_compositing.html"));
  RunTest(url, EXPECT_NO_GPU_PROCESS);
}

IN_PROC_BROWSER_TEST_F(GpuFeatureTest, WebGLAllowed) {
  GpuFeatureType type = GpuDataManager::GetInstance()->GetGpuFeatureType();
  EXPECT_EQ(type, 0);

  const FilePath url(FILE_PATH_LITERAL("feature_webgl.html"));
  RunTest(url, EXPECT_GPU_SWAP_BUFFERS);
}

IN_PROC_BROWSER_TEST_F(GpuFeatureTest, WebGLBlocked) {
  const std::string json_blacklist =
      "{\n"
      "  \"name\": \"gpu blacklist\",\n"
      "  \"version\": \"1.0\",\n"
      "  \"entries\": [\n"
      "    {\n"
      "      \"id\": 1,\n"
      "      \"blacklist\": [\n"
      "        \"webgl\"\n"
      "      ]\n"
      "    }\n"
      "  ]\n"
      "}";
  SetupBlacklist(json_blacklist);
  GpuFeatureType type = GpuDataManager::GetInstance()->GetGpuFeatureType();
  EXPECT_EQ(type, content::GPU_FEATURE_TYPE_WEBGL);

  const FilePath url(FILE_PATH_LITERAL("feature_webgl.html"));
  RunTest(url, EXPECT_NO_GPU_PROCESS);
}

class WebGLTest : public GpuFeatureTest {
 public:
  virtual void SetUpCommandLine(CommandLine* command_line) {
    GpuFeatureTest::SetUpCommandLine(command_line);
    command_line->AppendSwitch(switches::kDisableExperimentalWebGL);
  }
};

IN_PROC_BROWSER_TEST_F(WebGLTest, WebGLDisabled) {
  const FilePath url(FILE_PATH_LITERAL("feature_webgl.html"));
  RunTest(url, EXPECT_NO_GPU_PROCESS);
}

IN_PROC_BROWSER_TEST_F(GpuFeatureTest, MultisamplingAllowed) {
  GpuFeatureType type = GpuDataManager::GetInstance()->GetGpuFeatureType();
  EXPECT_EQ(type, 0);

  // Multisampling is not supported if running on top of osmesa.
  std::string use_gl = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
      switches::kUseGL);
  if (use_gl == gfx::kGLImplementationOSMesaName)
    return;

  const FilePath url(FILE_PATH_LITERAL("feature_multisampling.html"));
  RunTest(url, "\"TRUE\"", true);
}

IN_PROC_BROWSER_TEST_F(GpuFeatureTest, MultisamplingBlocked) {
  const std::string json_blacklist =
      "{\n"
      "  \"name\": \"gpu blacklist\",\n"
      "  \"version\": \"1.0\",\n"
      "  \"entries\": [\n"
      "    {\n"
      "      \"id\": 1,\n"
      "      \"blacklist\": [\n"
      "        \"multisampling\"\n"
      "      ]\n"
      "    }\n"
      "  ]\n"
      "}";
  SetupBlacklist(json_blacklist);
  GpuFeatureType type = GpuDataManager::GetInstance()->GetGpuFeatureType();
  EXPECT_EQ(type, content::GPU_FEATURE_TYPE_MULTISAMPLING);

  const FilePath url(FILE_PATH_LITERAL("feature_multisampling.html"));
  RunTest(url, "\"FALSE\"", true);
}

class WebGLMultisamplingTest : public GpuFeatureTest {
 public:
  virtual void SetUpCommandLine(CommandLine* command_line) {
    GpuFeatureTest::SetUpCommandLine(command_line);
    command_line->AppendSwitch(switches::kDisableGLMultisampling);
  }
};

IN_PROC_BROWSER_TEST_F(WebGLMultisamplingTest, MultisamplingDisabled) {
  const FilePath url(FILE_PATH_LITERAL("feature_multisampling.html"));
  RunTest(url, "\"FALSE\"", true);
}

class Canvas2DEnabledTest : public GpuFeatureTest {
 public:
  virtual void SetUpCommandLine(CommandLine* command_line) {
    GpuFeatureTest::SetUpCommandLine(command_line);
    command_line->AppendSwitch(switches::kEnableAccelerated2dCanvas);
  }
};

IN_PROC_BROWSER_TEST_F(Canvas2DEnabledTest, Canvas2DAllowed) {
  GpuFeatureType type = GpuDataManager::GetInstance()->GetGpuFeatureType();
  EXPECT_EQ(type, 0);

  const FilePath url(FILE_PATH_LITERAL("feature_canvas2d.html"));
  RunTest(url, EXPECT_GPU_SWAP_BUFFERS);
}

IN_PROC_BROWSER_TEST_F(Canvas2DEnabledTest, Canvas2DBlocked) {
  const std::string json_blacklist =
      "{\n"
      "  \"name\": \"gpu blacklist\",\n"
      "  \"version\": \"1.0\",\n"
      "  \"entries\": [\n"
      "    {\n"
      "      \"id\": 1,\n"
      "      \"blacklist\": [\n"
      "        \"accelerated_2d_canvas\"\n"
      "      ]\n"
      "    }\n"
      "  ]\n"
      "}";
  SetupBlacklist(json_blacklist);
  GpuFeatureType type = GpuDataManager::GetInstance()->GetGpuFeatureType();
  EXPECT_EQ(type, content::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS);

  const FilePath url(FILE_PATH_LITERAL("feature_canvas2d.html"));
  RunTest(url, EXPECT_NO_GPU_PROCESS);
}

class Canvas2DDisabledTest : public GpuFeatureTest {
 public:
  virtual void SetUpCommandLine(CommandLine* command_line) {
    GpuFeatureTest::SetUpCommandLine(command_line);
    command_line->AppendSwitch(switches::kDisableAccelerated2dCanvas);
  }
};

IN_PROC_BROWSER_TEST_F(Canvas2DDisabledTest, Canvas2DDisabled) {
  const FilePath url(FILE_PATH_LITERAL("feature_canvas2d.html"));
  RunTest(url, EXPECT_NO_GPU_PROCESS);
}

IN_PROC_BROWSER_TEST_F(GpuFeatureTest,
                       CanOpenPopupAndRenderWithWebGLCanvas) {
  const FilePath url(FILE_PATH_LITERAL("webgl_popup.html"));
  RunTest(url, "\"SUCCESS\"", false);
}

IN_PROC_BROWSER_TEST_F(GpuFeatureTest, CanOpenPopupAndRenderWith2DCanvas) {
  const FilePath url(FILE_PATH_LITERAL("canvas_popup.html"));
  RunTest(url, "\"SUCCESS\"", false);
}

class ThreadedCompositorTest : public GpuFeatureTest {
 public:
  virtual void SetUpCommandLine(CommandLine* command_line) {
    GpuFeatureTest::SetUpCommandLine(command_line);
    command_line->AppendSwitch(switches::kEnableThreadedCompositing);
  }
};

IN_PROC_BROWSER_TEST_F(ThreadedCompositorTest, DISABLED_ThreadedCompositor) {
  const FilePath url(FILE_PATH_LITERAL("feature_compositing.html"));
  RunTest(url, EXPECT_GPU_SWAP_BUFFERS);
}

}  // namespace anonymous

<commit_msg>Disable certain gpu feature tests for certain bots.<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 "base/command_line.h"
#include "base/file_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/path_service.h"
#include "base/test/trace_event_analyzer.h"
#include "base/version.h"
#include "chrome/browser/gpu_blacklist.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/test_launcher_utils.h"
#include "chrome/test/base/tracing.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/gpu_data_manager.h"
#include "content/public/common/content_switches.h"
#include "content/test/gpu/gpu_test_config.h"
#include "net/base/net_util.h"
#include "ui/gfx/gl/gl_switches.h"

using content::GpuDataManager;
using content::GpuFeatureType;

namespace {

typedef uint32 GpuResultFlags;
#define EXPECT_NO_GPU_PROCESS         GpuResultFlags(1<<0)
// Expect a SwapBuffers to occur (see gles2_cmd_decoder.cc).
#define EXPECT_GPU_SWAP_BUFFERS       GpuResultFlags(1<<1)

class GpuFeatureTest : public InProcessBrowserTest {
 public:
  GpuFeatureTest() {}

  virtual void SetUpInProcessBrowserTestFixture() {
    FilePath test_dir;
    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
    gpu_test_dir_ = test_dir.AppendASCII("gpu");
  }

  virtual void SetUpCommandLine(CommandLine* command_line) {
    // This enables DOM automation for tab contents.
    EnableDOMAutomation();

    InProcessBrowserTest::SetUpCommandLine(command_line);

    // Do not use mesa if real GPU is required.
    if (!command_line->HasSwitch("use-gpu-in-tests")) {
#if !defined(OS_MACOSX)
      CHECK(test_launcher_utils::OverrideGLImplementation(
          command_line, gfx::kGLImplementationOSMesaName)) <<
          "kUseGL must not be set by test framework code!";
#endif
    }
    command_line->AppendSwitch(switches::kDisablePopupBlocking);
    command_line->AppendSwitchASCII(switches::kWindowSize, "400,300");
  }

  void SetupBlacklist(const std::string& json_blacklist) {
    GpuBlacklist* blacklist = GpuBlacklist::GetInstance();
    ASSERT_TRUE(blacklist->LoadGpuBlacklist(
        "1.0", json_blacklist, GpuBlacklist::kAllOs));
    blacklist->UpdateGpuDataManager();
  }

  // If expected_reply is NULL, we don't check the reply content.
  void RunTest(const FilePath& url,
               const char* expected_reply,
               bool new_tab) {
    FilePath test_path;
    test_path = gpu_test_dir_.Append(url);
    ASSERT_TRUE(file_util::PathExists(test_path))
        << "Missing test file: " << test_path.value();

    ui_test_utils::DOMMessageQueue message_queue;
    if (new_tab) {
      ui_test_utils::NavigateToURLWithDisposition(
          browser(), net::FilePathToFileURL(test_path),
          NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_NONE);
    } else {
      ui_test_utils::NavigateToURL(
          browser(), net::FilePathToFileURL(test_path));
    }

    std::string result;
    // Wait for message indicating the test has finished running.
    ASSERT_TRUE(message_queue.WaitForMessage(&result));
    if (expected_reply)
      EXPECT_STREQ(expected_reply, result.c_str());
  }

  void RunTest(const FilePath& url, GpuResultFlags expectations) {
    using trace_analyzer::Query;
    using trace_analyzer::TraceAnalyzer;

    ASSERT_TRUE(tracing::BeginTracing("test_gpu"));

    // Have to use a new tab for the blacklist to work.
    RunTest(url, NULL, true);

    std::string json_events;
    ASSERT_TRUE(tracing::EndTracing(&json_events));

    scoped_ptr<TraceAnalyzer> analyzer(TraceAnalyzer::Create(json_events));
    analyzer->AssociateBeginEndEvents();
    trace_analyzer::TraceEventVector events;

    // This measurement is flaky, because the GPU process is sometimes
    // started before the test (always with force-compositing-mode on CrOS).
    if (expectations & EXPECT_NO_GPU_PROCESS) {
      EXPECT_EQ(0u, analyzer->FindEvents(
          Query::MatchBeginName("OnGraphicsInfoCollected"), &events));
    }

    // Check for swap buffers if expected:
    if (expectations & EXPECT_GPU_SWAP_BUFFERS) {
      EXPECT_GT(analyzer->FindEvents(Query::EventName() ==
                                     Query::String("SwapBuffers"), &events),
                size_t(0));
    }
  }

 protected:
  FilePath gpu_test_dir_;
};

IN_PROC_BROWSER_TEST_F(GpuFeatureTest, AcceleratedCompositingAllowed) {
  GpuFeatureType type = GpuDataManager::GetInstance()->GetGpuFeatureType();
  EXPECT_EQ(type, 0);

  const FilePath url(FILE_PATH_LITERAL("feature_compositing.html"));
  RunTest(url, EXPECT_GPU_SWAP_BUFFERS);
}

IN_PROC_BROWSER_TEST_F(GpuFeatureTest, AcceleratedCompositingBlocked) {
  const std::string json_blacklist =
      "{\n"
      "  \"name\": \"gpu blacklist\",\n"
      "  \"version\": \"1.0\",\n"
      "  \"entries\": [\n"
      "    {\n"
      "      \"id\": 1,\n"
      "      \"blacklist\": [\n"
      "        \"accelerated_compositing\"\n"
      "      ]\n"
      "    }\n"
      "  ]\n"
      "}";
  SetupBlacklist(json_blacklist);
  GpuFeatureType type = GpuDataManager::GetInstance()->GetGpuFeatureType();
  EXPECT_EQ(type, content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING);

  const FilePath url(FILE_PATH_LITERAL("feature_compositing.html"));
  RunTest(url, EXPECT_NO_GPU_PROCESS);
}

class AcceleratedCompositingTest : public GpuFeatureTest {
 public:
  virtual void SetUpCommandLine(CommandLine* command_line) {
    GpuFeatureTest::SetUpCommandLine(command_line);
    command_line->AppendSwitch(switches::kDisableAcceleratedCompositing);
  }
};

IN_PROC_BROWSER_TEST_F(AcceleratedCompositingTest,
                       AcceleratedCompositingDisabled) {
  const FilePath url(FILE_PATH_LITERAL("feature_compositing.html"));
  RunTest(url, EXPECT_NO_GPU_PROCESS);
}

IN_PROC_BROWSER_TEST_F(GpuFeatureTest, WebGLAllowed) {
  GpuFeatureType type = GpuDataManager::GetInstance()->GetGpuFeatureType();
  EXPECT_EQ(type, 0);

  const FilePath url(FILE_PATH_LITERAL("feature_webgl.html"));
  RunTest(url, EXPECT_GPU_SWAP_BUFFERS);
}

IN_PROC_BROWSER_TEST_F(GpuFeatureTest, WebGLBlocked) {
  const std::string json_blacklist =
      "{\n"
      "  \"name\": \"gpu blacklist\",\n"
      "  \"version\": \"1.0\",\n"
      "  \"entries\": [\n"
      "    {\n"
      "      \"id\": 1,\n"
      "      \"blacklist\": [\n"
      "        \"webgl\"\n"
      "      ]\n"
      "    }\n"
      "  ]\n"
      "}";
  SetupBlacklist(json_blacklist);
  GpuFeatureType type = GpuDataManager::GetInstance()->GetGpuFeatureType();
  EXPECT_EQ(type, content::GPU_FEATURE_TYPE_WEBGL);

  const FilePath url(FILE_PATH_LITERAL("feature_webgl.html"));
  RunTest(url, EXPECT_NO_GPU_PROCESS);
}

class WebGLTest : public GpuFeatureTest {
 public:
  virtual void SetUpCommandLine(CommandLine* command_line) {
    GpuFeatureTest::SetUpCommandLine(command_line);
    command_line->AppendSwitch(switches::kDisableExperimentalWebGL);
  }
};

IN_PROC_BROWSER_TEST_F(WebGLTest, WebGLDisabled) {
  const FilePath url(FILE_PATH_LITERAL("feature_webgl.html"));
  RunTest(url, EXPECT_NO_GPU_PROCESS);
}

IN_PROC_BROWSER_TEST_F(GpuFeatureTest, MultisamplingAllowed) {
  GpuFeatureType type = GpuDataManager::GetInstance()->GetGpuFeatureType();
  EXPECT_EQ(type, 0);

  // Multisampling is not supported if running on top of osmesa.
  std::string use_gl = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
      switches::kUseGL);
  if (use_gl == gfx::kGLImplementationOSMesaName)
    return;

#if defined(OS_LINUX)
  // Linux Intel uses mesa driver, where multisampling is not supported.
  GPUTestBotConfig test_bot;
  test_bot.LoadCurrentConfig(NULL);
  const std::vector<uint32>& gpu_vendor = test_bot.gpu_vendor();
  if (gpu_vendor.size() == 1 && gpu_vendor[0] == 0x8086)
    return;
#endif

  const FilePath url(FILE_PATH_LITERAL("feature_multisampling.html"));
  RunTest(url, "\"TRUE\"", true);
}

IN_PROC_BROWSER_TEST_F(GpuFeatureTest, MultisamplingBlocked) {
  const std::string json_blacklist =
      "{\n"
      "  \"name\": \"gpu blacklist\",\n"
      "  \"version\": \"1.0\",\n"
      "  \"entries\": [\n"
      "    {\n"
      "      \"id\": 1,\n"
      "      \"blacklist\": [\n"
      "        \"multisampling\"\n"
      "      ]\n"
      "    }\n"
      "  ]\n"
      "}";
  SetupBlacklist(json_blacklist);
  GpuFeatureType type = GpuDataManager::GetInstance()->GetGpuFeatureType();
  EXPECT_EQ(type, content::GPU_FEATURE_TYPE_MULTISAMPLING);

  const FilePath url(FILE_PATH_LITERAL("feature_multisampling.html"));
  RunTest(url, "\"FALSE\"", true);
}

class WebGLMultisamplingTest : public GpuFeatureTest {
 public:
  virtual void SetUpCommandLine(CommandLine* command_line) {
    GpuFeatureTest::SetUpCommandLine(command_line);
    command_line->AppendSwitch(switches::kDisableGLMultisampling);
  }
};

IN_PROC_BROWSER_TEST_F(WebGLMultisamplingTest, MultisamplingDisabled) {
  const FilePath url(FILE_PATH_LITERAL("feature_multisampling.html"));
  RunTest(url, "\"FALSE\"", true);
}

class Canvas2DEnabledTest : public GpuFeatureTest {
 public:
  virtual void SetUpCommandLine(CommandLine* command_line) {
    GpuFeatureTest::SetUpCommandLine(command_line);
    command_line->AppendSwitch(switches::kEnableAccelerated2dCanvas);
  }
};

IN_PROC_BROWSER_TEST_F(Canvas2DEnabledTest, Canvas2DAllowed) {
  GpuFeatureType type = GpuDataManager::GetInstance()->GetGpuFeatureType();
  EXPECT_EQ(type, 0);

  const FilePath url(FILE_PATH_LITERAL("feature_canvas2d.html"));

  GpuResultFlags expectations = EXPECT_GPU_SWAP_BUFFERS;
#if defined(OS_WIN)
  // Accelerated canvas 2D is not supported on XP.
  GPUTestBotConfig test_bot;
  test_bot.LoadCurrentConfig(NULL);
  if (test_bot.os() == GPUTestConfig::kOsWinXP)
    expectations = EXPECT_NO_GPU_PROCESS;
#endif
  RunTest(url, expectations);
}

IN_PROC_BROWSER_TEST_F(Canvas2DEnabledTest, Canvas2DBlocked) {
  const std::string json_blacklist =
      "{\n"
      "  \"name\": \"gpu blacklist\",\n"
      "  \"version\": \"1.0\",\n"
      "  \"entries\": [\n"
      "    {\n"
      "      \"id\": 1,\n"
      "      \"blacklist\": [\n"
      "        \"accelerated_2d_canvas\"\n"
      "      ]\n"
      "    }\n"
      "  ]\n"
      "}";
  SetupBlacklist(json_blacklist);
  GpuFeatureType type = GpuDataManager::GetInstance()->GetGpuFeatureType();
  EXPECT_EQ(type, content::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS);

  const FilePath url(FILE_PATH_LITERAL("feature_canvas2d.html"));
  RunTest(url, EXPECT_NO_GPU_PROCESS);
}

class Canvas2DDisabledTest : public GpuFeatureTest {
 public:
  virtual void SetUpCommandLine(CommandLine* command_line) {
    GpuFeatureTest::SetUpCommandLine(command_line);
    command_line->AppendSwitch(switches::kDisableAccelerated2dCanvas);
  }
};

IN_PROC_BROWSER_TEST_F(Canvas2DDisabledTest, Canvas2DDisabled) {
  const FilePath url(FILE_PATH_LITERAL("feature_canvas2d.html"));
  RunTest(url, EXPECT_NO_GPU_PROCESS);
}

IN_PROC_BROWSER_TEST_F(GpuFeatureTest,
                       CanOpenPopupAndRenderWithWebGLCanvas) {
  const FilePath url(FILE_PATH_LITERAL("webgl_popup.html"));
  RunTest(url, "\"SUCCESS\"", false);
}

IN_PROC_BROWSER_TEST_F(GpuFeatureTest, CanOpenPopupAndRenderWith2DCanvas) {
  const FilePath url(FILE_PATH_LITERAL("canvas_popup.html"));
  RunTest(url, "\"SUCCESS\"", false);
}

class ThreadedCompositorTest : public GpuFeatureTest {
 public:
  virtual void SetUpCommandLine(CommandLine* command_line) {
    GpuFeatureTest::SetUpCommandLine(command_line);
    command_line->AppendSwitch(switches::kEnableThreadedCompositing);
  }
};

IN_PROC_BROWSER_TEST_F(ThreadedCompositorTest, DISABLED_ThreadedCompositor) {
  const FilePath url(FILE_PATH_LITERAL("feature_compositing.html"));
  RunTest(url, EXPECT_GPU_SWAP_BUFFERS);
}

}  // namespace anonymous

<|endoftext|>


<commit_before>// This code emulates the 64x16/80x24 display controller.
//
// If the realtime mode is enabled, the timing of the original display
// controller is approximated.  Basically the ucode always checks to see
// if the card is busy before it sends any byte.  When a byte is received,
// the card asserts its busy flag until the requested operation is done.
// The timing to complete each operation is as follows
//    printable characters:
//        (see p. 6-8 and p. 6-13 of the 2200 service manual)
//        printable characters must wait until horizontal blanking
//        before they get saved into the display RAM, then busy is cleared.
//    screen clear:
//        (see p. 6-7 and p. 6-11 of the 2200 service manual)
//        the controller waits for vertical blanking, then it writes
//        a space to each character at the rate it would normally be
//        reading the bytes for display.  after all characters have
//        been written to spaces, the busy flag is cleared.
//    scroll event:
//        (see p. 6-11 of the 2200 service manual, called a "roll")
//        the description of the actions is hard to figure out without
//        detailed study of the schematic as several one-shots are
//        involved and I'm too lazy to decipher it.  it sounds like
//        after a short delay, a state machine writes the 64 characters
//        of the exposed row to spaces and then clears the busy flag.
//        instead, what the emulator implements is this:
//        the controller waits for a horizontal sync, then it writes
//        one row of characters to all spaces in the time it would
//        normally use to display one row of dots -- that is one
//        horizontal sweep period -- then busy is dropped.

/* character generation details
   + see p. 5-2 of the service manual (p 170 of 414)
        for 64x16
            - 5x7 dot matrix in a 7x15 character cell
                - scanline 1 is blank
                - scanlines 2-8 are 7 rows of character data
                - scanlines 9 is always blank
                - scanline 10 is optional cursor, which is 7 dots wide
                - scanlines 11-15 are blank
                - no underline
            - field is 256 rows; 1-240 are data, 241-256 are vblank
            - 60 Hz update rate
            - dot clock is 116 ns; char clock is 812 ns (7 dots)
            - 80 character times per scanline (65 uS)
        for 80x24
            - 8 rows of pixel data
            - 1 row of optional underline (>=0x80)
            - 1 row of cursor
            - 1 blank row
*/

#include "Ui.h"
#include "host.h"             // for dbglog
#include "IoCardDisplay.h"
#include "Scheduler.h"        // for Timer...() functions
#include "system2200.h"
#include "Terminal.h"
#include "Cpu2200.h"

#ifdef _MSC_VER
    #pragma warning( disable: 4127 )  // conditional expression is constant
#endif

static const bool do_dbg = false;  // turn on some debugging messages

// number of scanlines per display field
static const int num_scanlines = 256;

// horizontal refresh period = (1M us/s) / (60 frames/s * 256 rows/frame)
#define HSYNC_PERIOD (TIMER_US(65))

// vertical refresh period
#define VSYNC_PERIOD (HSYNC_PERIOD * num_scanlines)

// the logic of the card busy status is as follows.
//
// (1) the m_tmr_hsync timer is always running, no matter whether the user
//     wants realtime operation or not.  having this timer fire every 65 uS
//     hurts performance about 10% on my celeron 667 machine.  to minimize
//     this cost, once per vblank the state of the "realtime or not" boolean
//     is checked.  if realtime isn't requested, then the timer is set to
//     fire at the next vblank.  this cuts down on overhead by 256x.  the
//     reason for insisting it always run is that it cuts down on
//     complications of starting it/stopping it at arbitrary times.
//
// (2) the busy flag is always set on OBS.
//
// (3) as the character received by OBS is analyzed, some control codes
//     are acted upon and clear the busy state.  otherwise, the character's
//     effect is handled immediately and a small state machine is set up to
//     determine when to clear the busy state.  this state is advanced by
//     the m_tmr_hsync timer event.

// instance constructor
IoCardDisplay::IoCardDisplay(std::shared_ptr<Scheduler> scheduler,
                             std::shared_ptr<Cpu2200>   cpu,
                             int base_addr, int card_slot,
                             ui_screen_t screen_type) :
    m_scheduler(scheduler),
    m_cpu(cpu),
    m_base_addr(base_addr),
    m_slot(card_slot),
    m_selected(false),
    m_card_busy(false),
    m_screen_type(screen_type),
    m_terminal(nullptr),
    m_tmr_hsync(nullptr),
    m_realtime(true),
    m_hsync_count(0),
    m_busy_state(busy_state::IDLE)
{
    if (m_slot < 0) {
        // this is just a probe to query properties, so don't make a window
        return;
    }

    reset(true);

    m_terminal = std::make_unique<Terminal>(scheduler, nullptr,
                                            base_addr, 0, screen_type);
    assert(m_terminal);
}

// instance destructor
IoCardDisplay::~IoCardDisplay()
{
    if (m_slot >= 0) {
        reset(true);    // turns off handshakes in progress
        m_terminal = nullptr;
    }
}

const std::string
IoCardDisplay::getDescription() const
{
    return (m_screen_type == UI_SCREEN_64x16) ? "64x16 CRT Controller"
                                              : "80x24 CRT Controller";
}

const std::string
IoCardDisplay::getName() const
{
    return (m_screen_type == UI_SCREEN_64x16) ? "6312A" : "7011";
}

// return a list of the various base addresses a card can map to
// list of common I/O addresses for this device taken from p. 2-5 of
// the default comes first.
std::vector<int>
IoCardDisplay::getBaseAddresses() const
{
    std::vector<int> v {0x005, 0x006, 0x007 };
    return v;
}

// return the list of addresses that this specific card responds to
std::vector<int>
IoCardDisplay::getAddresses() const
{
    std::vector<int> v;
    v.push_back(m_base_addr);
    return v;
}

void
IoCardDisplay::reset(bool /*hard_reset*/)
{
    // reset card state
    m_busy_state = busy_state::IDLE;
    m_selected   = false;
    m_card_busy  = false;

    // get the horizontal sync timer going
    m_tmr_hsync = nullptr;
    m_hsync_count = 0;
    tcbHsync(0);
}

void
IoCardDisplay::select()
{
    if (do_dbg) {
        dbglog("display ABS\n");
    }

    m_selected = true;
    m_cpu->setDevRdy(!m_card_busy);
}

void
IoCardDisplay::deselect()
{
    if (do_dbg) {
        dbglog("display -ABS\n");
    }
    m_cpu->setDevRdy(false);

    m_selected = false;
}

void
IoCardDisplay::strobeOBS(int val)
{
    assert(m_busy_state == busy_state::IDLE);

    const uint8 val8 = val & 0xFF;

    if (do_dbg) {
        const char ch = (0x20 <= val8 && val8 < 0x7F) ? val8 : '.';
        dbglog("display OBS: Output of byte 0x%02x (%c)\n", val8, ch);
    }

    m_terminal->processChar(val8);

    if (system2200::isCpuSpeedRegulated()) {
        if (val8 == 0x03) {
            m_busy_state = busy_state::CLEAR1;
            m_card_busy = true;
#if 0
        } else if (val8 == 0x0A && cur_row == 15) {
            m_busy_state = busy_state::ROLL1;
            m_card_busy = true;
#endif
        } else if (val8 >= 0x10) {
            m_busy_state = busy_state::CHAR;
            m_card_busy = true;
        }
    }

    m_cpu->setDevRdy(!m_card_busy);
}

void
IoCardDisplay::strobeCBS(int val)
{
    val &= 0xFF;
#ifdef _DEBUG
    UI_warn("unexpected display CBS: Output of byte 0x%02x", val);
#endif
}

int
IoCardDisplay::getIB() const noexcept
{
    // the system uses this to determine screen size so effectively either
    //    SELECT PRINT 005(64), CO 005(64), LIST 005(64)
    // or
    //    SELECT PRINT 005(80), CO 005(80), LIST 005(80)
    // is performed on reset.
    return (m_screen_type == UI_SCREEN_80x24) ? 0x10 : 0x00;
}

// change of CPU Busy state
// because the display is write-only, we don't expect the CPU
// to poll us for input.
void
IoCardDisplay::setCpuBusy(bool busy)
{
    busy = busy; // make lint happy

    // it appears that except for reset, ucode only ever clears it,
    // and of course the IBS sets it back.
    if (do_dbg) {
        dbglog("display CPB%c\n", busy?'+':'-');
    }

    m_cpu->setDevRdy(!m_card_busy);
}

// horizontal sync timer callback
void
IoCardDisplay::tcbHsync(int arg)
{
    const bool regulated = system2200::isCpuSpeedRegulated();

    m_hsync_count++;

    int64 new_period = HSYNC_PERIOD;
    if (!regulated || (m_hsync_count < num_scanlines)) {
        // once per vertical refresh -- just to keep the timer alive
        new_period = VSYNC_PERIOD;
        m_hsync_count = 1;
    }

    // retrigger the timer
#if 0
    m_tmr_hsync = m_scheduler->createTimer(new_period,
                                            [&](){ tcbHsync(arg); });
#else
    m_tmr_hsync = m_scheduler->createTimer(new_period,
                            std::bind(&IoCardDisplay::tcbHsync, this, arg));
#endif

    // advance state machine
    switch (m_busy_state) {

        case busy_state::IDLE:
            break;

        case busy_state::CHAR:
            m_card_busy = false;
            m_busy_state = busy_state::IDLE;
            m_cpu->setDevRdy(true);
            break;

        case busy_state::CLEAR1:
            if (m_hsync_count == 1) {    // vblank
                m_busy_state = busy_state::CLEAR2;
            }
            break;
        case busy_state::CLEAR2:
            if (m_hsync_count == 1) {    // vblank
                m_card_busy = false;
                m_busy_state = busy_state::IDLE;
                m_cpu->setDevRdy(true);
            }
            break;

        case busy_state::ROLL1:
            m_busy_state = busy_state::ROLL2;
            break;
        case busy_state::ROLL2:
            m_card_busy = false;
            m_busy_state = busy_state::IDLE;
            m_cpu->setDevRdy(true);
            break;

        default:
            assert(false);
            break;
    }
}

// vim: ts=8:et:sw=4:smarttab
<commit_msg>gah: fix the display timing bug again<commit_after>// This code emulates the 64x16/80x24 display controller.
//
// If the realtime mode is enabled, the timing of the original display
// controller is approximated.  Basically the ucode always checks to see
// if the card is busy before it sends any byte.  When a byte is received,
// the card asserts its busy flag until the requested operation is done.
// The timing to complete each operation is as follows
//    printable characters:
//        (see p. 6-8 and p. 6-13 of the 2200 service manual)
//        printable characters must wait until horizontal blanking
//        before they get saved into the display RAM, then busy is cleared.
//    screen clear:
//        (see p. 6-7 and p. 6-11 of the 2200 service manual)
//        the controller waits for vertical blanking, then it writes
//        a space to each character at the rate it would normally be
//        reading the bytes for display.  after all characters have
//        been written to spaces, the busy flag is cleared.
//    scroll event:
//        (see p. 6-11 of the 2200 service manual, called a "roll")
//        the description of the actions is hard to figure out without
//        detailed study of the schematic as several one-shots are
//        involved and I'm too lazy to decipher it.  it sounds like
//        after a short delay, a state machine writes the 64 characters
//        of the exposed row to spaces and then clears the busy flag.
//        instead, what the emulator implements is this:
//        the controller waits for a horizontal sync, then it writes
//        one row of characters to all spaces in the time it would
//        normally use to display one row of dots -- that is one
//        horizontal sweep period -- then busy is dropped.

/* character generation details
   + see p. 5-2 of the service manual (p 170 of 414)
        for 64x16
            - 5x7 dot matrix in a 7x15 character cell
                - scanline 1 is blank
                - scanlines 2-8 are 7 rows of character data
                - scanlines 9 is always blank
                - scanline 10 is optional cursor, which is 7 dots wide
                - scanlines 11-15 are blank
                - no underline
            - field is 256 rows; 1-240 are data, 241-256 are vblank
            - 60 Hz update rate
            - dot clock is 116 ns; char clock is 812 ns (7 dots)
            - 80 character times per scanline (65 uS)
        for 80x24
            - 8 rows of pixel data
            - 1 row of optional underline (>=0x80)
            - 1 row of cursor
            - 1 blank row
*/

#include "Ui.h"
#include "host.h"             // for dbglog
#include "IoCardDisplay.h"
#include "Scheduler.h"        // for Timer...() functions
#include "system2200.h"
#include "Terminal.h"
#include "Cpu2200.h"

#ifdef _MSC_VER
    #pragma warning( disable: 4127 )  // conditional expression is constant
#endif

static const bool do_dbg = false;  // turn on some debugging messages

// number of scanlines per display field
static const int num_scanlines = 256;

// horizontal refresh period = (1M us/s) / (60 frames/s * 256 rows/frame)
#define HSYNC_PERIOD (TIMER_US(65))

// vertical refresh period
#define VSYNC_PERIOD (HSYNC_PERIOD * num_scanlines)

// the logic of the card busy status is as follows.
//
// (1) the m_tmr_hsync timer is always running, no matter whether the user
//     wants realtime operation or not.  having this timer fire every 65 uS
//     hurts performance about 10% on my celeron 667 machine.  to minimize
//     this cost, once per vblank the state of the "realtime or not" boolean
//     is checked.  if realtime isn't requested, then the timer is set to
//     fire at the next vblank.  this cuts down on overhead by 256x.  the
//     reason for insisting it always run is that it cuts down on
//     complications of starting it/stopping it at arbitrary times.
//
// (2) the busy flag is always set on OBS.
//
// (3) as the character received by OBS is analyzed, some control codes
//     are acted upon and clear the busy state.  otherwise, the character's
//     effect is handled immediately and a small state machine is set up to
//     determine when to clear the busy state.  this state is advanced by
//     the m_tmr_hsync timer event.

// instance constructor
IoCardDisplay::IoCardDisplay(std::shared_ptr<Scheduler> scheduler,
                             std::shared_ptr<Cpu2200>   cpu,
                             int base_addr, int card_slot,
                             ui_screen_t screen_type) :
    m_scheduler(scheduler),
    m_cpu(cpu),
    m_base_addr(base_addr),
    m_slot(card_slot),
    m_selected(false),
    m_card_busy(false),
    m_screen_type(screen_type),
    m_terminal(nullptr),
    m_tmr_hsync(nullptr),
    m_realtime(true),
    m_hsync_count(0),
    m_busy_state(busy_state::IDLE)
{
    if (m_slot < 0) {
        // this is just a probe to query properties, so don't make a window
        return;
    }

    reset(true);

    m_terminal = std::make_unique<Terminal>(scheduler, nullptr,
                                            base_addr, 0, screen_type);
    assert(m_terminal);
}

// instance destructor
IoCardDisplay::~IoCardDisplay()
{
    if (m_slot >= 0) {
        reset(true);    // turns off handshakes in progress
        m_terminal = nullptr;
    }
}

const std::string
IoCardDisplay::getDescription() const
{
    return (m_screen_type == UI_SCREEN_64x16) ? "64x16 CRT Controller"
                                              : "80x24 CRT Controller";
}

const std::string
IoCardDisplay::getName() const
{
    return (m_screen_type == UI_SCREEN_64x16) ? "6312A" : "7011";
}

// return a list of the various base addresses a card can map to
// list of common I/O addresses for this device taken from p. 2-5 of
// the default comes first.
std::vector<int>
IoCardDisplay::getBaseAddresses() const
{
    std::vector<int> v {0x005, 0x006, 0x007 };
    return v;
}

// return the list of addresses that this specific card responds to
std::vector<int>
IoCardDisplay::getAddresses() const
{
    std::vector<int> v;
    v.push_back(m_base_addr);
    return v;
}

void
IoCardDisplay::reset(bool /*hard_reset*/)
{
    // reset card state
    m_busy_state = busy_state::IDLE;
    m_selected   = false;
    m_card_busy  = false;

    // get the horizontal sync timer going
    m_tmr_hsync = nullptr;
    m_hsync_count = 0;
    tcbHsync(0);
}

void
IoCardDisplay::select()
{
    if (do_dbg) {
        dbglog("display ABS\n");
    }

    m_selected = true;
    m_cpu->setDevRdy(!m_card_busy);
}

void
IoCardDisplay::deselect()
{
    if (do_dbg) {
        dbglog("display -ABS\n");
    }
    m_cpu->setDevRdy(false);

    m_selected = false;
}

void
IoCardDisplay::strobeOBS(int val)
{
    assert(m_busy_state == busy_state::IDLE);

    const uint8 val8 = val & 0xFF;

    if (do_dbg) {
        const char ch = (0x20 <= val8 && val8 < 0x7F) ? val8 : '.';
        dbglog("display OBS: Output of byte 0x%02x (%c)\n", val8, ch);
    }

    m_terminal->processChar(val8);

    if (system2200::isCpuSpeedRegulated()) {
        if (val8 == 0x03) {
            m_busy_state = busy_state::CLEAR1;
            m_card_busy = true;
#if 0
        } else if (val8 == 0x0A && cur_row == 15) {
            m_busy_state = busy_state::ROLL1;
            m_card_busy = true;
#endif
        } else if (val8 >= 0x10) {
            m_busy_state = busy_state::CHAR;
            m_card_busy = true;
        }
    }

    m_cpu->setDevRdy(!m_card_busy);
}

void
IoCardDisplay::strobeCBS(int val)
{
    val &= 0xFF;
#ifdef _DEBUG
    UI_warn("unexpected display CBS: Output of byte 0x%02x", val);
#endif
}

int
IoCardDisplay::getIB() const noexcept
{
    // the system uses this to determine screen size so effectively either
    //    SELECT PRINT 005(64), CO 005(64), LIST 005(64)
    // or
    //    SELECT PRINT 005(80), CO 005(80), LIST 005(80)
    // is performed on reset.
    return (m_screen_type == UI_SCREEN_80x24) ? 0x10 : 0x00;
}

// change of CPU Busy state
// because the display is write-only, we don't expect the CPU
// to poll us for input.
void
IoCardDisplay::setCpuBusy(bool busy)
{
    busy = busy; // make lint happy

    // it appears that except for reset, ucode only ever clears it,
    // and of course the IBS sets it back.
    if (do_dbg) {
        dbglog("display CPB%c\n", busy?'+':'-');
    }

    m_cpu->setDevRdy(!m_card_busy);
}

// horizontal sync timer callback
void
IoCardDisplay::tcbHsync(int arg)
{
    const bool regulated = system2200::isCpuSpeedRegulated();

    m_hsync_count++;

    int64 new_period = HSYNC_PERIOD;
    if (!regulated || (m_hsync_count >= num_scanlines)) {
        // once per vertical refresh -- just to keep the timer alive
        new_period = VSYNC_PERIOD;
        m_hsync_count = 1;
    }

    // retrigger the timer
#if 0
    m_tmr_hsync = m_scheduler->createTimer(new_period,
                                            [&](){ tcbHsync(arg); });
#else
    m_tmr_hsync = m_scheduler->createTimer(new_period,
                            std::bind(&IoCardDisplay::tcbHsync, this, arg));
#endif

    // advance state machine
    switch (m_busy_state) {

        case busy_state::IDLE:
            break;

        case busy_state::CHAR:
            m_card_busy = false;
            m_busy_state = busy_state::IDLE;
            m_cpu->setDevRdy(true);
            break;

        case busy_state::CLEAR1:
            if (m_hsync_count == 1) {    // vblank
                m_busy_state = busy_state::CLEAR2;
            }
            break;
        case busy_state::CLEAR2:
            if (m_hsync_count == 1) {    // vblank
                m_card_busy = false;
                m_busy_state = busy_state::IDLE;
                m_cpu->setDevRdy(true);
            }
            break;

        case busy_state::ROLL1:
            m_busy_state = busy_state::ROLL2;
            break;
        case busy_state::ROLL2:
            m_card_busy = false;
            m_busy_state = busy_state::IDLE;
            m_cpu->setDevRdy(true);
            break;

        default:
            assert(false);
            break;
    }
}

// vim: ts=8:et:sw=4:smarttab
<|endoftext|>


<commit_before>/*
 * gVirtuS -- A GPGPU transparent virtualization component.
 *
 * Copyright (C) 2009-2010  The University of Napoli Parthenope at Naples.
 *
 * This file is part of gVirtuS.
 *
 * gVirtuS is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * gVirtuS 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with gVirtuS; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Written by: Giuseppe Coviello <giuseppe.coviello@uniparthenope.it>,
 *             Department of Applied Science
 */

#include <vector>
#include <cstring>
#include <cstdio>

/**
 * @file   Backend.cpp
 * @author Giuseppe Coviello <giuseppe.coviello@uniparthenope.it>
 * @date   Wed Sep 30 12:29:26 2009
 *
 * @brief
 *
 *
 */

#include "Backend.h"

#include <iostream>

#include "Process.h"
#include <dlfcn.h>
#include <string>
#include <cstring>

using namespace std;

Backend::Backend(vector<string> &plugins) {
    mPlugins = plugins;
}

void Backend::Start(Communicator * communicator) {
    communicator->Serve();
    //aux communicator
    while (true) {
        Communicator *client =
                const_cast<Communicator *> (communicator->Accept());

        Process *process = new Process(client, mPlugins);
        process->Start(NULL);
    }
}

void Backend::EventOccurred(std::string& event, void* object) {
    std::cout << "EventOccurred: " << event << std::endl;
}
<commit_msg>Added logger<commit_after>/*
 * gVirtuS -- A GPGPU transparent virtualization component.
 *
 * Copyright (C) 2009-2010  The University of Napoli Parthenope at Naples.
 *
 * This file is part of gVirtuS.
 *
 * gVirtuS is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * gVirtuS 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with gVirtuS; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Written by: Giuseppe Coviello <giuseppe.coviello@uniparthenope.it>,
 *             Department of Applied Science
 */

#include <vector>
#include <cstring>
#include <cstdio>

/**
 * @file   Backend.cpp
 * @author Giuseppe Coviello <giuseppe.coviello@uniparthenope.it>
 * @date   Wed Sep 30 12:29:26 2009
 *
 * @brief
 *
 *
 */

#include "Backend.h"

#include <iostream>

#include "Process.h"
#include <dlfcn.h>
#include <string>
#include <cstring>

using namespace std;
using namespace log4cplus;

Backend::Backend(vector<string> &plugins) {
    logger=Logger::getInstance(LOG4CPLUS_TEXT("Backend"));
    mPlugins = plugins;
}

void Backend::Start(Communicator * communicator) {
    communicator->Serve();
    //aux communicator
    while (true) {
        Communicator *client =
                const_cast<Communicator *> (communicator->Accept());
        LOG4CPLUS_DEBUG(logger, "Connection accepted" );
        Process *process = new Process(client, mPlugins);
        process->Start(NULL);
    }
}

void Backend::EventOccurred(std::string& event, void* object) {
    //std::cout << "EventOccurred: " << event << std::endl;
    LOG4CPLUS_DEBUG(logger, "EventOccurred: " << event);
}
<|endoftext|>


<commit_before>/*
 *  Copyright 2010-2011 Fabric Technologies Inc. All rights reserved.
 */

#include "BooleanAdapter.h"
#include "ConstStringAdapter.h"
#include "Context.h"
#include "IntegerAdapter.h"
#include "SizeAdapter.h"
#include "StringAdapter.h"
#include "Manager.h"
#include "ModuleBuilder.h"
#include "FunctionBuilder.h"
#include "BasicBlockBuilder.h"
#include "OverloadNames.h"

#include <Fabric/Core/RT/BooleanDesc.h>
#include <Fabric/Core/Util/Format.h>

namespace Fabric
{
  namespace CG
  {
    BooleanAdapter::BooleanAdapter( RC::ConstHandle<Manager> const &manager, RC::ConstHandle<RT::BooleanDesc> const &booleanDesc )
      : SimpleAdapter( manager, booleanDesc )
      , m_booleanDesc( booleanDesc )
    {
    }

    llvm::Type const *BooleanAdapter::buildLLVMRawType( RC::Handle<Context> const &context ) const
    {
      return llvm::Type::getInt1Ty( context->getLLVMContext() );
    }

    void BooleanAdapter::llvmCompileToModule( ModuleBuilder &moduleBuilder ) const
    {
      if ( moduleBuilder.haveCompiledToModule( getCodeName() ) )
        return;

      RC::Handle<Context> context = moduleBuilder.getContext();

      RC::ConstHandle<IntegerAdapter> integerAdapter = getManager()->getIntegerAdapter();
      integerAdapter->llvmCompileToModule( moduleBuilder );
      RC::ConstHandle<SizeAdapter> sizeAdapter = getManager()->getSizeAdapter();
      sizeAdapter->llvmCompileToModule( moduleBuilder );
      RC::ConstHandle<StringAdapter> stringAdapter = getManager()->getStringAdapter();
      stringAdapter->llvmCompileToModule( moduleBuilder );
      RC::ConstHandle<ConstStringAdapter> constStringAdapter = getManager()->getConstStringAdapter();
      constStringAdapter->llvmCompileToModule( moduleBuilder );

      static const bool buildFunctions = true;

      {
        std::string name = constructOverloadName( stringAdapter, this );
        std::vector< FunctionParam > params;
        params.push_back( FunctionParam( "stringLValue", stringAdapter, USAGE_LVALUE ) );
        params.push_back( FunctionParam( "booleanRValue", this, USAGE_RVALUE ) );
        FunctionBuilder functionBuilder( moduleBuilder, name, ExprType(), params );
        if ( buildFunctions )
        {
          llvm::Value *stringLValue = functionBuilder[0];
          llvm::Value *booleanRValue = functionBuilder[1];
          BasicBlockBuilder basicBlockBuilder( functionBuilder );

          basicBlockBuilder->SetInsertPoint( functionBuilder.createBasicBlock( "entry" ) );
          llvm::BasicBlock *trueBB = functionBuilder.createBasicBlock( "true" );
          llvm::BasicBlock *falseBB = functionBuilder.createBasicBlock( "false" );
          llvm::BasicBlock *mergeBB = functionBuilder.createBasicBlock( "merge" );
          basicBlockBuilder->CreateCondBr( booleanRValue, trueBB, falseBB );

          basicBlockBuilder->SetInsertPoint( trueBB );
          ExprValue trueExprValue( constStringAdapter, USAGE_RVALUE, context, constStringAdapter->llvmConst( basicBlockBuilder, "true", 4 ) );
          llvm::Value *trueStringRValue = stringAdapter->llvmCast( basicBlockBuilder, trueExprValue );
          basicBlockBuilder->CreateBr( mergeBB );

          basicBlockBuilder->SetInsertPoint( falseBB );
          ExprValue falseExprValue( constStringAdapter, USAGE_RVALUE, context, constStringAdapter->llvmConst( basicBlockBuilder, "false", 5 ) );
          llvm::Value *falseStringRValue = stringAdapter->llvmCast( basicBlockBuilder, falseExprValue );
          basicBlockBuilder->CreateBr( mergeBB );

          basicBlockBuilder->SetInsertPoint( mergeBB );
          llvm::PHINode *stringRValue = basicBlockBuilder->CreatePHI( stringAdapter->llvmRType( context ), "stringRValue" );
          stringRValue->addIncoming( trueStringRValue, trueBB );
          stringRValue->addIncoming( falseStringRValue, falseBB );
          stringAdapter->llvmAssign( basicBlockBuilder, stringLValue, stringRValue );
          basicBlockBuilder->CreateRetVoid();
        }
      }

      /*
      // [pzion 20110202] It's unclear that we want booleans to automatically cast to numerics

      {
        std::string name = constructOverloadName( byteDesc, ExprType( this, USAGE_RVALUE ) );
        std::vector< FunctionParam > params;
        params.push_back( FunctionParam( "booleanRValue", this, USAGE_RVALUE ) );
        FunctionBuilder functionBuilder( moduleBuilder, name, ExprType( byteDesc, USAGE_RVALUE ), params );
        llvm::Value *booleanRValue = functionBuilder[0];
        BasicBlockBuilder basicBlockBuilder( functionBuilder );
        basicBlockBuilder->SetInsertPoint( functionBuilder.createBasicBlock( "entry" ) );
        llvm::Value *byteRValue = basicBlockBuilder->CreateZExt( booleanRValue, llvmRType() );
        basicBlockBuilder->CreateRet( byteRValue );
      }

      {
        std::string name = constructOverloadName( integerDesc, ExprType( this, USAGE_RVALUE ) );
        std::vector< FunctionParam > params;
        params.push_back( FunctionParam( "booleanRValue", this, USAGE_RVALUE ) );
        FunctionBuilder functionBuilder( moduleBuilder, name, ExprType( integerDesc, USAGE_RVALUE ), params );
        llvm::Value *booleanRValue = functionBuilder[0];
        BasicBlockBuilder basicBlockBuilder( functionBuilder );
        basicBlockBuilder->SetInsertPoint( functionBuilder.createBasicBlock( "entry" ) );
        llvm::Value *integerRValue = basicBlockBuilder->CreateZExt( booleanRValue, llvmRType() );
        basicBlockBuilder->CreateRet( integerRValue );
      }

      {
        std::string name = constructOverloadName( scalarDesc, ExprType( this, USAGE_RVALUE ) );
        std::vector< FunctionParam > params;
        params.push_back( FunctionParam( "booleanRValue", this, USAGE_RVALUE ) );
        FunctionBuilder functionBuilder( moduleBuilder, name, ExprType( scalarDesc, USAGE_RVALUE ), params );
        llvm::Value *booleanRValue = functionBuilder[0];
        BasicBlockBuilder basicBlockBuilder( functionBuilder );
        basicBlockBuilder->SetInsertPoint( functionBuilder.createBasicBlock( "entry" ) );
        llvm::Value *scalarRValue = basicBlockBuilder->CreateUIToFP( booleanRValue, llvmRType() );
        basicBlockBuilder->CreateRet( scalarRValue );
      }
      */

      {
        std::string name = uniOpOverloadName( UNI_OP_BIT_NOT, this );
        std::vector< FunctionParam > params;
        params.push_back( FunctionParam( "rValue", this, USAGE_RVALUE ) );
        FunctionBuilder functionBuilder( moduleBuilder, name, ExprType( this, USAGE_RVALUE ), params );
        if ( buildFunctions )
        {
          llvm::Value *rValue = functionBuilder[0];
          BasicBlockBuilder basicBlockBuilder( functionBuilder );
          basicBlockBuilder->SetInsertPoint( functionBuilder.createBasicBlock( "entry" ) );
          llvm::Value *notRValue = basicBlockBuilder->CreateNot( rValue );
          basicBlockBuilder->CreateRet( notRValue );
        }
      }

      {
        std::string name = binOpOverloadName( BIN_OP_BIT_OR, this, this );
        std::vector< FunctionParam > params;
        params.push_back( FunctionParam( "lhsRValue", this, USAGE_RVALUE ) );
        params.push_back( FunctionParam( "rhsRValue", this, USAGE_RVALUE ) );
        FunctionBuilder functionBuilder( moduleBuilder, name, ExprType( this, USAGE_RVALUE ), params );
        if ( buildFunctions )
        {
          llvm::Value *lhsRValue = functionBuilder[0];
          llvm::Value *rhsRValue = functionBuilder[1];
          BasicBlockBuilder basicBlockBuilder( functionBuilder );
          basicBlockBuilder->SetInsertPoint( functionBuilder.createBasicBlock( "entry" ) );
          llvm::Value *resultRValue = basicBlockBuilder->CreateOr( lhsRValue, rhsRValue );
          basicBlockBuilder->CreateRet( resultRValue );
        }
      }

      {
        std::string name = binOpOverloadName( BIN_OP_BIT_AND, this, this );
        std::vector< FunctionParam > params;
        params.push_back( FunctionParam( "lhsRValue", this, USAGE_RVALUE ) );
        params.push_back( FunctionParam( "rhsRValue", this, USAGE_RVALUE ) );
        FunctionBuilder functionBuilder( moduleBuilder, name, ExprType( this, USAGE_RVALUE ), params );
        if ( buildFunctions )
        {
          llvm::Value *lhsRValue = functionBuilder[0];
          llvm::Value *rhsRValue = functionBuilder[1];
          BasicBlockBuilder basicBlockBuilder( functionBuilder );
          basicBlockBuilder->SetInsertPoint( functionBuilder.createBasicBlock( "entry" ) );
          llvm::Value *resultRValue = basicBlockBuilder->CreateAnd( lhsRValue, rhsRValue );
          basicBlockBuilder->CreateRet( resultRValue );
        }
      }

      {
        std::string name = binOpOverloadName( BIN_OP_BIT_XOR, this, this );
        std::vector< FunctionParam > params;
        params.push_back( FunctionParam( "lhsRValue", this, USAGE_RVALUE ) );
        params.push_back( FunctionParam( "rhsRValue", this, USAGE_RVALUE ) );
        FunctionBuilder functionBuilder( moduleBuilder, name, ExprType( this, USAGE_RVALUE ), params );
        if ( buildFunctions )
        {
          llvm::Value *lhsRValue = functionBuilder[0];
          llvm::Value *rhsRValue = functionBuilder[1];
          BasicBlockBuilder basicBlockBuilder( functionBuilder );
          basicBlockBuilder->SetInsertPoint( functionBuilder.createBasicBlock( "entry" ) );
          llvm::Value *resultRValue = basicBlockBuilder->CreateXor( lhsRValue, rhsRValue );
          basicBlockBuilder->CreateRet( resultRValue );
        }
      }

      {
        std::string name = binOpOverloadName( BIN_OP_EQ, this, this );
        std::vector< FunctionParam > params;
        params.push_back( FunctionParam( "lhsRValue", this, USAGE_RVALUE ) );
        params.push_back( FunctionParam( "rhsRValue", this, USAGE_RVALUE ) );
        FunctionBuilder functionBuilder( moduleBuilder, name, ExprType( this, USAGE_RVALUE ), params );
        if ( buildFunctions )
        {
          llvm::Value *lhsRValue = functionBuilder[0];
          llvm::Value *rhsRValue = functionBuilder[1];
          BasicBlockBuilder basicBlockBuilder( functionBuilder );
          basicBlockBuilder->SetInsertPoint( functionBuilder.createBasicBlock( "entry" ) );
          llvm::Value *resultRValue = basicBlockBuilder->CreateICmpEQ( lhsRValue, rhsRValue );
          basicBlockBuilder->CreateRet( resultRValue );
        }
      }

      {
        std::string name = binOpOverloadName( BIN_OP_NE, this, this );
        std::vector< FunctionParam > params;
        params.push_back( FunctionParam( "lhsRValue", this, USAGE_RVALUE ) );
        params.push_back( FunctionParam( "rhsRValue", this, USAGE_RVALUE ) );
        FunctionBuilder functionBuilder( moduleBuilder, name, ExprType( this, USAGE_RVALUE ), params );
        if ( buildFunctions )
        {
          llvm::Value *lhsRValue = functionBuilder[0];
          llvm::Value *rhsRValue = functionBuilder[1];
          BasicBlockBuilder basicBlockBuilder( functionBuilder );
          basicBlockBuilder->SetInsertPoint( functionBuilder.createBasicBlock( "entry" ) );
          llvm::Value *resultRValue = basicBlockBuilder->CreateICmpNE( lhsRValue, rhsRValue );
          basicBlockBuilder->CreateRet( resultRValue );
        }
      }

      {
        std::string name = methodOverloadName( "hash", this );
        std::vector<FunctionParam> params;
        params.push_back( FunctionParam( "rValue", this, USAGE_RVALUE ) );
        FunctionBuilder functionBuilder( moduleBuilder, name, ExprType( sizeAdapter, USAGE_RVALUE ), params );
        if ( buildFunctions )
        {
          llvm::Value *rValue = functionBuilder[0];
          BasicBlockBuilder basicBlockBuilder( functionBuilder );
          basicBlockBuilder->SetInsertPoint( functionBuilder.createBasicBlock( "entry" ) );
          basicBlockBuilder->CreateRet(
            basicBlockBuilder->CreateZExt(
              rValue,
              sizeAdapter->llvmRType( context )
              )
            );
        }
      }

      {
        std::string name = methodOverloadName( "compare", this, this );
        std::vector< FunctionParam > params;
        params.push_back( FunctionParam( "lhsRValue", this, USAGE_RVALUE ) );
        params.push_back( FunctionParam( "rhsRValue", this, USAGE_RVALUE ) );
        FunctionBuilder functionBuilder( moduleBuilder, name, ExprType( integerAdapter, USAGE_RVALUE ), params );
        if ( buildFunctions )
        {
          llvm::Value *lhsRValue = functionBuilder[0];
          llvm::Value *rhsRValue = functionBuilder[1];
          BasicBlockBuilder basicBlockBuilder( functionBuilder );
          basicBlockBuilder->SetInsertPoint( functionBuilder.createBasicBlock( "entry" ) );
          llvm::Value *lhsRValueAsInteger = basicBlockBuilder->CreateZExt( lhsRValue, integerAdapter->llvmRType( context ) );
          llvm::Value *rhsRValueAsInteger = basicBlockBuilder->CreateZExt( rhsRValue, integerAdapter->llvmRType( context ) );
          basicBlockBuilder->CreateRet(
            basicBlockBuilder->CreateSub(
              lhsRValueAsInteger,
              rhsRValueAsInteger
              )
            );
        }
      }
    }

    llvm::Constant *BooleanAdapter::llvmConst( RC::Handle<Context> const &context, bool value ) const
    {
      return llvm::ConstantInt::get( llvmRType( context ), value, false );
    }

    std::string BooleanAdapter::toString( void const *data ) const
    {
      return _( m_booleanDesc->getValue(data) );
    }

    llvm::Constant *BooleanAdapter::llvmDefaultValue( BasicBlockBuilder &basicBlockBuilder ) const
    {
      return llvmConst( basicBlockBuilder.getContext(), m_booleanDesc->getValue( m_booleanDesc->getDefaultData() ) );
    }
  };
};
<commit_msg>Fix leak in Boolean to String conversion<commit_after>/*
 *  Copyright 2010-2011 Fabric Technologies Inc. All rights reserved.
 */

#include "BooleanAdapter.h"
#include "ConstStringAdapter.h"
#include "Context.h"
#include "IntegerAdapter.h"
#include "SizeAdapter.h"
#include "StringAdapter.h"
#include "Manager.h"
#include "ModuleBuilder.h"
#include "FunctionBuilder.h"
#include "BasicBlockBuilder.h"
#include "OverloadNames.h"

#include <Fabric/Core/RT/BooleanDesc.h>
#include <Fabric/Core/Util/Format.h>

namespace Fabric
{
  namespace CG
  {
    BooleanAdapter::BooleanAdapter( RC::ConstHandle<Manager> const &manager, RC::ConstHandle<RT::BooleanDesc> const &booleanDesc )
      : SimpleAdapter( manager, booleanDesc )
      , m_booleanDesc( booleanDesc )
    {
    }

    llvm::Type const *BooleanAdapter::buildLLVMRawType( RC::Handle<Context> const &context ) const
    {
      return llvm::Type::getInt1Ty( context->getLLVMContext() );
    }

    void BooleanAdapter::llvmCompileToModule( ModuleBuilder &moduleBuilder ) const
    {
      if ( moduleBuilder.haveCompiledToModule( getCodeName() ) )
        return;

      RC::Handle<Context> context = moduleBuilder.getContext();

      RC::ConstHandle<IntegerAdapter> integerAdapter = getManager()->getIntegerAdapter();
      integerAdapter->llvmCompileToModule( moduleBuilder );
      RC::ConstHandle<SizeAdapter> sizeAdapter = getManager()->getSizeAdapter();
      sizeAdapter->llvmCompileToModule( moduleBuilder );
      RC::ConstHandle<StringAdapter> stringAdapter = getManager()->getStringAdapter();
      stringAdapter->llvmCompileToModule( moduleBuilder );
      RC::ConstHandle<ConstStringAdapter> constStringAdapter = getManager()->getConstStringAdapter();
      constStringAdapter->llvmCompileToModule( moduleBuilder );

      static const bool buildFunctions = true;

      {
        std::string name = constructOverloadName( stringAdapter, this );
        std::vector< FunctionParam > params;
        params.push_back( FunctionParam( "stringLValue", stringAdapter, USAGE_LVALUE ) );
        params.push_back( FunctionParam( "booleanRValue", this, USAGE_RVALUE ) );
        FunctionBuilder functionBuilder( moduleBuilder, name, ExprType(), params );
        if ( buildFunctions )
        {
          llvm::Value *stringLValue = functionBuilder[0];
          llvm::Value *booleanRValue = functionBuilder[1];
          BasicBlockBuilder basicBlockBuilder( functionBuilder );

          basicBlockBuilder->SetInsertPoint( functionBuilder.createBasicBlock( "entry" ) );
          llvm::BasicBlock *trueBB = functionBuilder.createBasicBlock( "true" );
          llvm::BasicBlock *falseBB = functionBuilder.createBasicBlock( "false" );
          basicBlockBuilder->CreateCondBr( booleanRValue, trueBB, falseBB );

          basicBlockBuilder->SetInsertPoint( trueBB );
          ExprValue trueExprValue( constStringAdapter, USAGE_RVALUE, context, constStringAdapter->llvmConst( basicBlockBuilder, "true", 4 ) );
          llvm::Value *trueStringRValue = stringAdapter->llvmCast( basicBlockBuilder, trueExprValue );
          stringAdapter->llvmAssign( basicBlockBuilder, stringLValue, trueStringRValue );
          stringAdapter->llvmDispose( basicBlockBuilder, trueStringRValue );
          basicBlockBuilder->CreateRetVoid();

          basicBlockBuilder->SetInsertPoint( falseBB );
          ExprValue falseExprValue( constStringAdapter, USAGE_RVALUE, context, constStringAdapter->llvmConst( basicBlockBuilder, "false", 5 ) );
          llvm::Value *falseStringRValue = stringAdapter->llvmCast( basicBlockBuilder, falseExprValue );
          stringAdapter->llvmAssign( basicBlockBuilder, stringLValue, falseStringRValue );
          stringAdapter->llvmDispose( basicBlockBuilder, falseStringRValue );
          basicBlockBuilder->CreateRetVoid();
        }
      }

      /*
      // [pzion 20110202] It's unclear that we want booleans to automatically cast to numerics

      {
        std::string name = constructOverloadName( byteDesc, ExprType( this, USAGE_RVALUE ) );
        std::vector< FunctionParam > params;
        params.push_back( FunctionParam( "booleanRValue", this, USAGE_RVALUE ) );
        FunctionBuilder functionBuilder( moduleBuilder, name, ExprType( byteDesc, USAGE_RVALUE ), params );
        llvm::Value *booleanRValue = functionBuilder[0];
        BasicBlockBuilder basicBlockBuilder( functionBuilder );
        basicBlockBuilder->SetInsertPoint( functionBuilder.createBasicBlock( "entry" ) );
        llvm::Value *byteRValue = basicBlockBuilder->CreateZExt( booleanRValue, llvmRType() );
        basicBlockBuilder->CreateRet( byteRValue );
      }

      {
        std::string name = constructOverloadName( integerDesc, ExprType( this, USAGE_RVALUE ) );
        std::vector< FunctionParam > params;
        params.push_back( FunctionParam( "booleanRValue", this, USAGE_RVALUE ) );
        FunctionBuilder functionBuilder( moduleBuilder, name, ExprType( integerDesc, USAGE_RVALUE ), params );
        llvm::Value *booleanRValue = functionBuilder[0];
        BasicBlockBuilder basicBlockBuilder( functionBuilder );
        basicBlockBuilder->SetInsertPoint( functionBuilder.createBasicBlock( "entry" ) );
        llvm::Value *integerRValue = basicBlockBuilder->CreateZExt( booleanRValue, llvmRType() );
        basicBlockBuilder->CreateRet( integerRValue );
      }

      {
        std::string name = constructOverloadName( scalarDesc, ExprType( this, USAGE_RVALUE ) );
        std::vector< FunctionParam > params;
        params.push_back( FunctionParam( "booleanRValue", this, USAGE_RVALUE ) );
        FunctionBuilder functionBuilder( moduleBuilder, name, ExprType( scalarDesc, USAGE_RVALUE ), params );
        llvm::Value *booleanRValue = functionBuilder[0];
        BasicBlockBuilder basicBlockBuilder( functionBuilder );
        basicBlockBuilder->SetInsertPoint( functionBuilder.createBasicBlock( "entry" ) );
        llvm::Value *scalarRValue = basicBlockBuilder->CreateUIToFP( booleanRValue, llvmRType() );
        basicBlockBuilder->CreateRet( scalarRValue );
      }
      */

      {
        std::string name = uniOpOverloadName( UNI_OP_BIT_NOT, this );
        std::vector< FunctionParam > params;
        params.push_back( FunctionParam( "rValue", this, USAGE_RVALUE ) );
        FunctionBuilder functionBuilder( moduleBuilder, name, ExprType( this, USAGE_RVALUE ), params );
        if ( buildFunctions )
        {
          llvm::Value *rValue = functionBuilder[0];
          BasicBlockBuilder basicBlockBuilder( functionBuilder );
          basicBlockBuilder->SetInsertPoint( functionBuilder.createBasicBlock( "entry" ) );
          llvm::Value *notRValue = basicBlockBuilder->CreateNot( rValue );
          basicBlockBuilder->CreateRet( notRValue );
        }
      }

      {
        std::string name = binOpOverloadName( BIN_OP_BIT_OR, this, this );
        std::vector< FunctionParam > params;
        params.push_back( FunctionParam( "lhsRValue", this, USAGE_RVALUE ) );
        params.push_back( FunctionParam( "rhsRValue", this, USAGE_RVALUE ) );
        FunctionBuilder functionBuilder( moduleBuilder, name, ExprType( this, USAGE_RVALUE ), params );
        if ( buildFunctions )
        {
          llvm::Value *lhsRValue = functionBuilder[0];
          llvm::Value *rhsRValue = functionBuilder[1];
          BasicBlockBuilder basicBlockBuilder( functionBuilder );
          basicBlockBuilder->SetInsertPoint( functionBuilder.createBasicBlock( "entry" ) );
          llvm::Value *resultRValue = basicBlockBuilder->CreateOr( lhsRValue, rhsRValue );
          basicBlockBuilder->CreateRet( resultRValue );
        }
      }

      {
        std::string name = binOpOverloadName( BIN_OP_BIT_AND, this, this );
        std::vector< FunctionParam > params;
        params.push_back( FunctionParam( "lhsRValue", this, USAGE_RVALUE ) );
        params.push_back( FunctionParam( "rhsRValue", this, USAGE_RVALUE ) );
        FunctionBuilder functionBuilder( moduleBuilder, name, ExprType( this, USAGE_RVALUE ), params );
        if ( buildFunctions )
        {
          llvm::Value *lhsRValue = functionBuilder[0];
          llvm::Value *rhsRValue = functionBuilder[1];
          BasicBlockBuilder basicBlockBuilder( functionBuilder );
          basicBlockBuilder->SetInsertPoint( functionBuilder.createBasicBlock( "entry" ) );
          llvm::Value *resultRValue = basicBlockBuilder->CreateAnd( lhsRValue, rhsRValue );
          basicBlockBuilder->CreateRet( resultRValue );
        }
      }

      {
        std::string name = binOpOverloadName( BIN_OP_BIT_XOR, this, this );
        std::vector< FunctionParam > params;
        params.push_back( FunctionParam( "lhsRValue", this, USAGE_RVALUE ) );
        params.push_back( FunctionParam( "rhsRValue", this, USAGE_RVALUE ) );
        FunctionBuilder functionBuilder( moduleBuilder, name, ExprType( this, USAGE_RVALUE ), params );
        if ( buildFunctions )
        {
          llvm::Value *lhsRValue = functionBuilder[0];
          llvm::Value *rhsRValue = functionBuilder[1];
          BasicBlockBuilder basicBlockBuilder( functionBuilder );
          basicBlockBuilder->SetInsertPoint( functionBuilder.createBasicBlock( "entry" ) );
          llvm::Value *resultRValue = basicBlockBuilder->CreateXor( lhsRValue, rhsRValue );
          basicBlockBuilder->CreateRet( resultRValue );
        }
      }

      {
        std::string name = binOpOverloadName( BIN_OP_EQ, this, this );
        std::vector< FunctionParam > params;
        params.push_back( FunctionParam( "lhsRValue", this, USAGE_RVALUE ) );
        params.push_back( FunctionParam( "rhsRValue", this, USAGE_RVALUE ) );
        FunctionBuilder functionBuilder( moduleBuilder, name, ExprType( this, USAGE_RVALUE ), params );
        if ( buildFunctions )
        {
          llvm::Value *lhsRValue = functionBuilder[0];
          llvm::Value *rhsRValue = functionBuilder[1];
          BasicBlockBuilder basicBlockBuilder( functionBuilder );
          basicBlockBuilder->SetInsertPoint( functionBuilder.createBasicBlock( "entry" ) );
          llvm::Value *resultRValue = basicBlockBuilder->CreateICmpEQ( lhsRValue, rhsRValue );
          basicBlockBuilder->CreateRet( resultRValue );
        }
      }

      {
        std::string name = binOpOverloadName( BIN_OP_NE, this, this );
        std::vector< FunctionParam > params;
        params.push_back( FunctionParam( "lhsRValue", this, USAGE_RVALUE ) );
        params.push_back( FunctionParam( "rhsRValue", this, USAGE_RVALUE ) );
        FunctionBuilder functionBuilder( moduleBuilder, name, ExprType( this, USAGE_RVALUE ), params );
        if ( buildFunctions )
        {
          llvm::Value *lhsRValue = functionBuilder[0];
          llvm::Value *rhsRValue = functionBuilder[1];
          BasicBlockBuilder basicBlockBuilder( functionBuilder );
          basicBlockBuilder->SetInsertPoint( functionBuilder.createBasicBlock( "entry" ) );
          llvm::Value *resultRValue = basicBlockBuilder->CreateICmpNE( lhsRValue, rhsRValue );
          basicBlockBuilder->CreateRet( resultRValue );
        }
      }

      {
        std::string name = methodOverloadName( "hash", this );
        std::vector<FunctionParam> params;
        params.push_back( FunctionParam( "rValue", this, USAGE_RVALUE ) );
        FunctionBuilder functionBuilder( moduleBuilder, name, ExprType( sizeAdapter, USAGE_RVALUE ), params );
        if ( buildFunctions )
        {
          llvm::Value *rValue = functionBuilder[0];
          BasicBlockBuilder basicBlockBuilder( functionBuilder );
          basicBlockBuilder->SetInsertPoint( functionBuilder.createBasicBlock( "entry" ) );
          basicBlockBuilder->CreateRet(
            basicBlockBuilder->CreateZExt(
              rValue,
              sizeAdapter->llvmRType( context )
              )
            );
        }
      }

      {
        std::string name = methodOverloadName( "compare", this, this );
        std::vector< FunctionParam > params;
        params.push_back( FunctionParam( "lhsRValue", this, USAGE_RVALUE ) );
        params.push_back( FunctionParam( "rhsRValue", this, USAGE_RVALUE ) );
        FunctionBuilder functionBuilder( moduleBuilder, name, ExprType( integerAdapter, USAGE_RVALUE ), params );
        if ( buildFunctions )
        {
          llvm::Value *lhsRValue = functionBuilder[0];
          llvm::Value *rhsRValue = functionBuilder[1];
          BasicBlockBuilder basicBlockBuilder( functionBuilder );
          basicBlockBuilder->SetInsertPoint( functionBuilder.createBasicBlock( "entry" ) );
          llvm::Value *lhsRValueAsInteger = basicBlockBuilder->CreateZExt( lhsRValue, integerAdapter->llvmRType( context ) );
          llvm::Value *rhsRValueAsInteger = basicBlockBuilder->CreateZExt( rhsRValue, integerAdapter->llvmRType( context ) );
          basicBlockBuilder->CreateRet(
            basicBlockBuilder->CreateSub(
              lhsRValueAsInteger,
              rhsRValueAsInteger
              )
            );
        }
      }
    }

    llvm::Constant *BooleanAdapter::llvmConst( RC::Handle<Context> const &context, bool value ) const
    {
      return llvm::ConstantInt::get( llvmRType( context ), value, false );
    }

    std::string BooleanAdapter::toString( void const *data ) const
    {
      return _( m_booleanDesc->getValue(data) );
    }

    llvm::Constant *BooleanAdapter::llvmDefaultValue( BasicBlockBuilder &basicBlockBuilder ) const
    {
      return llvmConst( basicBlockBuilder.getContext(), m_booleanDesc->getValue( m_booleanDesc->getDefaultData() ) );
    }
  };
};
<|endoftext|>


<commit_before>/*
 *  Copyright 2010-2011 Fabric Technologies Inc. All rights reserved.
 */

#include <Fabric/EDK/EDK.h>

#include "CImg.h"

using namespace Fabric::EDK;
IMPLEMENT_FABRIC_EDK_ENTRIES

using namespace cimg_library;

FABRIC_EXT_EXPORT void FabricCIMGDecode(
  KL::Data data,
  KL::Size dataSize,
  KL::Size &imageWidth,
  KL::Size &imageHeight,
  KL::VariableArray<KL::RGBA> &imagePixels
  )
{
#if defined(FABRIC_OS_WINDOWS)
  char const *dir = getenv("APPDATA");
  if(dir == NULL)
    dir = getenv("TEMP");
  if(dir == NULL)
    dir = getenv("TMP");
  if(dir == NULL)
    Fabric::EDK::throwException("CIMG extension: environment variable APP_DATA or TMP or TEMP is undefined");
  KL::String fileName( _tempnam( dir, "tmpfab_" ) );
#else
  KL::String fileName(tmpnam(NULL));
#endif

  // save the file to disk
  FILE * file = fopen(fileName.data(),"wb");
  if(!file)
    Fabric::EDK::throwException("CIMG extension: Cannot write to temporary file.");
  fwrite(data,dataSize,1,file);
  fclose(file);
  file = NULL;

  CImg<unsigned char> img(fileName.data());
  unsigned char * imgData = img.data();
  imageWidth = img.width();
  imageHeight = img.height();

  printf("width %d, height %d\n",(int)imageWidth,(int)imageHeight);

  size_t nbPixels = imageWidth * imageHeight;
  size_t offsetG = nbPixels;
  size_t offsetB = nbPixels * 2;

  imagePixels.resize(nbPixels);
  for(size_t i=0;i<nbPixels;i++,offsetG++,offsetB++)
  {
    imagePixels[i].r = imgData[i];
    imagePixels[i].g = imgData[offsetG];
    imagePixels[i].b = imgData[offsetB];
    imagePixels[i].a = 255;
  }
}

<commit_msg>issue-98: remove printf<commit_after>/*
 *  Copyright 2010-2011 Fabric Technologies Inc. All rights reserved.
 */

#include <Fabric/EDK/EDK.h>

#include "CImg.h"

using namespace Fabric::EDK;
IMPLEMENT_FABRIC_EDK_ENTRIES

using namespace cimg_library;

FABRIC_EXT_EXPORT void FabricCIMGDecode(
  KL::Data data,
  KL::Size dataSize,
  KL::Size &imageWidth,
  KL::Size &imageHeight,
  KL::VariableArray<KL::RGBA> &imagePixels
  )
{
#if defined(FABRIC_OS_WINDOWS)
  char const *dir = getenv("APPDATA");
  if(dir == NULL)
    dir = getenv("TEMP");
  if(dir == NULL)
    dir = getenv("TMP");
  if(dir == NULL)
    Fabric::EDK::throwException("CIMG extension: environment variable APP_DATA or TMP or TEMP is undefined");
  KL::String fileName( _tempnam( dir, "tmpfab_" ) );
#else
  KL::String fileName(tmpnam(NULL));
#endif

  // save the file to disk
  FILE * file = fopen(fileName.data(),"wb");
  if(!file)
    Fabric::EDK::throwException("CIMG extension: Cannot write to temporary file.");
  fwrite(data,dataSize,1,file);
  fclose(file);
  file = NULL;

  CImg<unsigned char> img(fileName.data());
  unsigned char * imgData = img.data();
  imageWidth = img.width();
  imageHeight = img.height();

  size_t nbPixels = imageWidth * imageHeight;
  size_t offsetG = nbPixels;
  size_t offsetB = nbPixels * 2;

  imagePixels.resize(nbPixels);
  for(size_t i=0;i<nbPixels;i++,offsetG++,offsetB++)
  {
    imagePixels[i].r = imgData[i];
    imagePixels[i].g = imgData[offsetG];
    imagePixels[i].b = imgData[offsetB];
    imagePixels[i].a = 255;
  }
}

<|endoftext|>