<commit_before>// Main Sniffer code

const int num_channels = 12;

#include "sniffer.h"
#include "protocol_headers.h"
#include "util.h"
#include <cstdlib>
#include <cstring>
#include <string>
#include <pcap.h>
#include <map>
#include <set>
#include <iostream>

using namespace std;

int macstat_flag = 0;

static pcap_t *handle = NULL;
static int datalink;
char * interface;

int current_channel = 0;

float max_time = 60;
float round_time;

float channel_prob[num_channels+1];
float channel_time[num_channels+1];
int channel_packets[num_channels+1];

map<string,int> mac_count[num_channels+1][4];

multimap<string,string> mac_timestamp;

// Place the interface into monitor mode
// Special code for Ubuntu (or similar systems) which use crazy Network Managers
void set_monitor_mode(char * iface) {
  interface = iface;
  char * const argv[] = {(char*)("iwconfig"),iface,(char*)("mode"),(char*)("monitor"),0};
  int ret = run_command(argv);
  if ( ret ) {
    debug("Probably on an Ubuntu system. Trying to set monitor using ifconfig technique.");
    char * const ifconfig_down[] = {(char*)("ifconfig"),iface,(char*)("down"),0};
    char * const ifconfig_up[] = {(char*)("ifconfig"),iface,(char*)("up"),0};
    ret = run_command(ifconfig_down);
    if ( ret ) {
      error("Interface error. Quitting.");
      abort();
    }
    ret = run_command(argv);
    if ( ret ) {
      error("Interface error. Quitting.");
      abort();
    }
    ret = run_command(ifconfig_up);
    if ( ret ) {
      error("Interface error. Quitting.");
      abort();
    }
  }
}

// Set up the interface, by setting to monitor mode, non-blocked
// Also, initialize the globals
void initialize(char * interface) {
  round_time = max_time/5.0f;

  if ( handle ) {
    error("Trying to reinitialize using interface %s",interface);
    abort();
  }

  char errbuf[BUFSIZ];

  set_monitor_mode(interface);

  handle = pcap_open_live(interface, BUFSIZ, 1, 1000, errbuf);
  if (handle == NULL) {
    error("Couldn't open interface %s. Error: %s",interface,errbuf);
    abort();
  }

  if ( pcap_setnonblock(handle,1,errbuf) == -1 ) {
    error("Couldn't set to non-blocking mode. Error: %s",errbuf);
    abort();
  }

  datalink = pcap_datalink(handle);

  verbose("Opened interface %s.",interface);
  debug("Datalink is %d.", datalink);

  for ( int i = 1 ; i <= num_channels ; i++ ) {
    channel_prob[i] = 1.0/num_channels;
    channel_time[i] = 0;
    channel_packets[i] = 0;
  }
}

// Convert MAC into more useful form and mark all relevant info in the
// global structures
void handleMAC(const u_char * mac, int pos) {
  char mac_c_str[13];
  mac_c_str[0] = 0;
  for ( int i = 0 ; i < 6 ; i++ ) {
    sprintf(mac_c_str,"%s%02X",mac_c_str,mac[i]);
  }
  string mac_str(mac_c_str);
  mac_count[current_channel][pos][mac_str]++;
  time_t t = time(NULL);
  mac_timestamp.insert(make_pair(mac_str,string(ctime(&t))));
  debug("MAC %d : %s",pos,mac_c_str);
}

// Strip away extra headers, and get to the MAC addresses
// Pass them to handleMAC
void handlePacket(const u_char* packet, int length) {
  if ( packet == NULL ) {
    return;
  }

  if ( datalink ==	DLT_PRISM_HEADER ) {
    prism_header* rth1 = (prism_header*)(packet);
    packet = packet + rth1->msglen;
    length -= rth1->msglen;
  }

  if ( datalink == DLT_IEEE802_11_RADIO ) {
    ieee80211_radiotap_header* rth2 = (ieee80211_radiotap_header*)(packet);
    packet = packet + rth2->it_len;
    length -= rth2->it_len;
  }

  for ( int i = 0 ; i < 4 ; i++ ) {
    if ( 9+i*6 < length ) {
      handleMAC(packet+4+(i*6),i);
    }
  }

  channel_packets[current_channel]++;
}

// Use run_command (defined in util.*) to change channel
void change_channel(int channel) {
  if ( channel < 1 || channel > num_channels ) {
    error("Impossible to switch to channel %d. Quitting.",channel);
    abort();
  }
  current_channel = channel;
  char channel_no[3];
  sprintf(channel_no,"%d",channel);
  char * const argv[] = {(char*)"iwconfig",interface,(char*)"channel",channel_no,0};
  run_command(argv);
  verbose("Changed to channel %d",channel);
}

static Timer ch_time;

// Mark the current timing onto the channel
void mark_time() {
  channel_time[current_channel]+=ch_time.get_time();
}

// Move to next channel and reset channel timer
void switch_to_next_channel() {
  mark_time();
  change_channel((current_channel % num_channels) + 1);
  ch_time.reset();
}

// Re-weight the time slices
void recalculate_probs() {
  const float min_speed_adder = 0.01;
  float speed[num_channels+1];
  float total_speed = 0;
  for ( int i = 1 ; i <= num_channels ; i++ ) {
    debug("Packets on channel %02d = %d",i,channel_packets[i]);
    speed[i] = channel_packets[i]/channel_time[i];
    speed[i] += min_speed_adder;
    total_speed += speed[i];
  }

  for ( int i = 1 ; i <= num_channels ; i++ ) {
    channel_prob[i] = speed[i] / total_speed;
  }

  verbose("Recalculated time allotted per channel (Greater time for busier channels)");
}

// Change parameters to more useful form for pcap
void callback(u_char *user,const struct pcap_pkthdr* pkthdr,const u_char* packet) {
  handlePacket(packet,pkthdr->len);
}

// Capture packets until main timer gets over
// Keep switching channels in a timely fashion
void capture_packets() {
  Timer timer;
  switch_to_next_channel();
  bool end_of_capturing = false;
  bool end_of_round = false;
  while ( true ) {
    if ( timer.get_time() >= max_time ) {
      end_of_capturing = true;
    }
    if ( pcap_dispatch(handle,1,callback,NULL) ) {
      debug("<<<Channel %02d timer: %f; Total timer: %f>>>",current_channel,ch_time.get_time(),timer.get_time());
    }
    if ( ch_time.get_time() > channel_prob[current_channel] * round_time ) {
      if ( current_channel==num_channels ) {
        mark_time();
        recalculate_probs();
        if ( end_of_capturing ) {
          break;
        }
      }
      switch_to_next_channel();
    }
  }
}

// Display collected info in a handy format
void print_info() {
  cout << "\n\n";
  int overall_total_mac_count = 0;
  int overall_total_packets_captured = 0;
  float overall_total_time = 0;
  set<string> overall_macs;
  bool suppressed = false;
  for ( int i = 1 ; i <= num_channels ; i++ ) {
    if ( channel_packets[i] == 0 ) {
      suppressed = true;
      continue;
    }
    int total_unique_mac_count = 0;
    int total_mac_count = 0;
    if ( is_verbose() ) {
      cout << "Channel #" << i << ":\n";
    }
    map<string,int> channel_mac_counts;
    for ( int j = 0 ; j < 4 ; j++ ) {
      for ( map<string,int>::iterator it = mac_count[i][j].begin() ; it != mac_count[i][j].end() ; it++ ) {
        channel_mac_counts[it->first] += it->second;
        overall_macs.insert(it->first);
      }
    }
    for ( map<string,int>::iterator it = channel_mac_counts.begin() ; it != channel_mac_counts.end() ; it++ ) {
      if ( is_verbose() ) {
        cout << it->first << " : " << it->second << endl;
      }
      total_mac_count += it->second;
      total_unique_mac_count += 1;
    }
    cout << "In channel " << i << ":\n";
    cout << " Number of unique MACs seen = " << total_unique_mac_count << endl;
    cout << " Total number of MACs seen  = " << total_mac_count << endl;
    cout << " Total packets captured     = " << channel_packets[i] << endl;
    cout << " Packet capture rate        = " << (channel_packets[i]/channel_time[i]) << " packets/sec" << endl;
    cout << "\n";
    overall_total_mac_count += total_mac_count;
    overall_total_packets_captured += channel_packets[i];
    overall_total_time += channel_time[i];
  }
  if ( suppressed ) {
    cout << "Note: Output for empty channels suppressed.\n";
  }
  if ( macstat_flag ) {
    cout << "\nMAC Stats: \n";
    string prev_mac = "";
    string prev_ts = "";
    int ts_count = 1;
    for ( multimap<string,string>::iterator it = mac_timestamp.begin() ; it != mac_timestamp.end() ; it++ ) {
      string mac = it->first;
      if ( it->second != prev_ts || mac != prev_mac ) {
        if ( ts_count > 1 ) {
          cout << " x " << ts_count;
        }
        ts_count = 1;
        cout << endl;
      } else {
        ts_count++;
      }
      if ( mac != prev_mac ) {
        cout << "  " << mac << " - " << mac_timestamp.count(mac) << endl;
        ts_count = 1;
        prev_ts = "";
      }
      if ( prev_ts != it->second ) {
        string temp = it->second;
        temp.erase(temp.length()-1,1);
        cout << "    " << temp;
      }
      prev_mac = mac;
      prev_ts = it->second;
    }
    if ( ts_count > 1 ) {
      cout << " x " << ts_count;
    }
    cout << "\n\n";
  }
  cout << "Overall:\n";
  cout << " Number of unique MACs seen = " << overall_macs.size() << endl;
  cout << " Total number of MACs seen  = " << overall_total_mac_count << endl;
  cout << " Total packets captured     = " << overall_total_packets_captured << endl;
  cout << " Packet capture rate        = " << overall_total_packets_captured/overall_total_time << " packets/sec" << endl;
  cout << "\n";
}
<commit_msg>Improve readability<commit_after>// Main Sniffer code

const int num_channels = 12;

#include "sniffer.h"
#include "protocol_headers.h"
#include "util.h"
#include <cstdlib>
#include <cstring>
#include <string>
#include <pcap.h>
#include <map>
#include <set>
#include <iostream>

using namespace std;

int macstat_flag = 0;

static pcap_t *handle = NULL;
static int datalink;
char * interface;

int current_channel = 0;

float max_time = 60;
float round_time;

float channel_prob[num_channels+1];
float channel_time[num_channels+1];
int channel_packets[num_channels+1];

map<string,int> mac_count[num_channels+1][4];

multimap<string,string> mac_timestamp;

// Place the interface into monitor mode
// Special code for Ubuntu (or similar systems) which use crazy Network Managers
void set_monitor_mode(char * iface) {
  interface = iface;
  char * const argv[] = {(char*)("iwconfig"),iface,(char*)("mode"),(char*)("monitor"),0};
  int ret = run_command(argv);
  if ( ret ) {
    debug("Probably on an Ubuntu system. Trying to set monitor using ifconfig technique.");
    char * const ifconfig_down[] = {(char*)("ifconfig"),iface,(char*)("down"),0};
    char * const ifconfig_up[] = {(char*)("ifconfig"),iface,(char*)("up"),0};
    ret = run_command(ifconfig_down);
    if ( ret ) {
      error("Interface error. Quitting.");
      abort();
    }
    ret = run_command(argv);
    if ( ret ) {
      error("Interface error. Quitting.");
      abort();
    }
    ret = run_command(ifconfig_up);
    if ( ret ) {
      error("Interface error. Quitting.");
      abort();
    }
  }
}

// Set up the interface, by setting to monitor mode, non-blocked
// Also, initialize the globals
void initialize(char * interface) {
  round_time = max_time/5.0f;

  if ( handle ) {
    error("Trying to reinitialize using interface %s",interface);
    abort();
  }

  char errbuf[BUFSIZ];

  set_monitor_mode(interface);

  handle = pcap_open_live(interface, BUFSIZ, 1, 1000, errbuf);
  if (handle == NULL) {
    error("Couldn't open interface %s. Error: %s",interface,errbuf);
    abort();
  }

  if ( pcap_setnonblock(handle,1,errbuf) == -1 ) {
    error("Couldn't set to non-blocking mode. Error: %s",errbuf);
    abort();
  }

  datalink = pcap_datalink(handle);

  verbose("Opened interface %s.",interface);
  debug("Datalink is %d.", datalink);

  for ( int i = 1 ; i <= num_channels ; i++ ) {
    channel_prob[i] = 1.0/num_channels;
    channel_time[i] = 0;
    channel_packets[i] = 0;
  }
}

// Convert MAC into more useful form and mark all relevant info in the
// global structures
void handleMAC(const u_char * mac, int pos) {
  char mac_c_str[13];
  mac_c_str[0] = 0;
  for ( int i = 0 ; i < 6 ; i++ ) {
    sprintf(mac_c_str,"%s%02X",mac_c_str,mac[i]);
  }
  string mac_str(mac_c_str);
  mac_count[current_channel][pos][mac_str]++;
  time_t t = time(NULL);
  mac_timestamp.insert(make_pair(mac_str,string(ctime(&t))));
  debug("MAC %d : %s",pos,mac_c_str);
}

// Strip away extra headers, and get to the MAC addresses
// Pass them to handleMAC
void handlePacket(const u_char* packet, int length) {
  if ( packet == NULL ) {
    return;
  }

  if ( datalink ==	DLT_PRISM_HEADER ) {
    prism_header* rth1 = (prism_header*)(packet);
    packet = packet + rth1->msglen;
    length -= rth1->msglen;
  }

  if ( datalink == DLT_IEEE802_11_RADIO ) {
    ieee80211_radiotap_header* rth2 = (ieee80211_radiotap_header*)(packet);
    packet = packet + rth2->it_len;
    length -= rth2->it_len;
  }

  for ( int i = 0 ; i < 4 ; i++ ) {
    if ( 9+i*6 < length ) {
      handleMAC(packet+4+(i*6),i);
    }
  }

  channel_packets[current_channel]++;
}

// Use run_command (defined in util.*) to change channel
void change_channel(int channel) {
  if ( channel < 1 || channel > num_channels ) {
    error("Impossible to switch to channel %d. Quitting.",channel);
    abort();
  }
  current_channel = channel;
  char channel_no[3];
  sprintf(channel_no,"%d",channel);
  char * const argv[] = {(char*)"iwconfig",interface,(char*)"channel",channel_no,0};
  run_command(argv);
  verbose("Changed to channel %d",channel);
}

static Timer ch_time;

// Mark the current timing onto the channel
void mark_time() {
  channel_time[current_channel]+=ch_time.get_time();
}

// Move to next channel and reset channel timer
void switch_to_next_channel() {
  mark_time();
  change_channel((current_channel % num_channels) + 1);
  ch_time.reset();
}

// Re-weight the time slices
void recalculate_probs() {
  const float min_speed_adder = 0.01;
  float speed[num_channels+1];
  float total_speed = 0;
  for ( int i = 1 ; i <= num_channels ; i++ ) {
    debug("Packets on channel %02d = %d",i,channel_packets[i]);
    speed[i] = channel_packets[i]/channel_time[i];
    speed[i] += min_speed_adder;
    total_speed += speed[i];
  }

  for ( int i = 1 ; i <= num_channels ; i++ ) {
    channel_prob[i] = speed[i] / total_speed;
  }

  verbose("Recalculated time allotted per channel (Greater time for busier channels)");
}

// Change parameters to more useful form for pcap
void callback(u_char *user,const struct pcap_pkthdr* pkthdr,const u_char* packet) {
  handlePacket(packet,pkthdr->len);
}

// Capture packets until main timer gets over
// Keep switching channels in a timely fashion
void capture_packets() {
  Timer timer;
  switch_to_next_channel();
  bool end_of_capturing = false;
  bool end_of_round = false;
  while ( true ) {
    if ( timer.get_time() >= max_time ) {
      end_of_capturing = true;
    }
    if ( pcap_dispatch(handle,1,callback,NULL) ) {
      debug("<<<Channel %02d timer: %f; Total timer: %f>>>",current_channel,ch_time.get_time(),timer.get_time());
    }
    if ( ch_time.get_time() > channel_prob[current_channel] * round_time ) {
      if ( current_channel==num_channels ) {
        mark_time();
        recalculate_probs();
        if ( end_of_capturing ) {
          break;
        }
      }
      switch_to_next_channel();
    }
  }
}

// Display collected info in a handy format
void print_info() {
  cout << "\n\n";
  int overall_total_mac_count = 0;
  int overall_total_packets_captured = 0;
  float overall_total_time = 0;
  set<string> overall_macs;
  bool suppressed = false;
  for ( int i = 1 ; i <= num_channels ; i++ ) {
    if ( channel_packets[i] == 0 ) {
      suppressed = true;
      continue;
    }
    int total_unique_mac_count = 0;
    int total_mac_count = 0;
    if ( is_verbose() ) {
      cout << "Channel #" << i << ":\n";
    }
    map<string,int> channel_mac_counts;
    for ( int j = 0 ; j < 4 ; j++ ) {
      for ( map<string,int>::iterator it = mac_count[i][j].begin() ; it != mac_count[i][j].end() ; it++ ) {
        channel_mac_counts[it->first] += it->second;
        overall_macs.insert(it->first);
      }
    }
    for ( map<string,int>::iterator it = channel_mac_counts.begin() ; it != channel_mac_counts.end() ; it++ ) {
      if ( is_verbose() ) {
        cout << "  " << it->first << " : " << it->second << endl;
      }
      total_mac_count += it->second;
      total_unique_mac_count += 1;
    }
    cout << "In channel " << i << ":\n";
    cout << " Number of unique MACs seen = " << total_unique_mac_count << endl;
    cout << " Total number of MACs seen  = " << total_mac_count << endl;
    cout << " Total packets captured     = " << channel_packets[i] << endl;
    cout << " Packet capture rate        = " << (channel_packets[i]/channel_time[i]) << " packets/sec" << endl;
    cout << "\n";
    overall_total_mac_count += total_mac_count;
    overall_total_packets_captured += channel_packets[i];
    overall_total_time += channel_time[i];
  }
  if ( suppressed ) {
    cout << "Note: Output for empty channels suppressed.\n";
  }
  if ( macstat_flag ) {
    cout << "\nMAC Stats: \n";
    string prev_mac = "";
    string prev_ts = "";
    int ts_count = 1;
    for ( multimap<string,string>::iterator it = mac_timestamp.begin() ; it != mac_timestamp.end() ; it++ ) {
      string mac = it->first;
      if ( it->second != prev_ts || mac != prev_mac ) {
        if ( ts_count > 1 ) {
          cout << " x " << ts_count;
        }
        ts_count = 1;
        cout << endl;
      } else {
        ts_count++;
      }
      if ( mac != prev_mac ) {
        cout << "  " << mac << " - " << mac_timestamp.count(mac) << endl;
        ts_count = 1;
        prev_ts = "";
      }
      if ( prev_ts != it->second ) {
        string temp = it->second;
        temp.erase(temp.length()-1,1);
        cout << "    " << temp;
      }
      prev_mac = mac;
      prev_ts = it->second;
    }
    if ( ts_count > 1 ) {
      cout << " x " << ts_count;
    }
    cout << "\n\n";
  }
  cout << "Overall:\n";
  cout << " Number of unique MACs seen = " << overall_macs.size() << endl;
  cout << " Total number of MACs seen  = " << overall_total_mac_count << endl;
  cout << " Total packets captured     = " << overall_total_packets_captured << endl;
  cout << " Packet capture rate        = " << overall_total_packets_captured/overall_total_time << " packets/sec" << endl;
  cout << "\n";
}
<|endoftext|>


<commit_before>#include <osg/Geode>
#include <osg/ShapeDrawable>
#include <osg/Material>
#include <osg/Texture2D>
#include <osg/MatrixTransform>
#include <osg/PositionAttitudeTransform>
#include <osg/BlendFunc>
#include <osg/ClearNode>
#include <osg/Projection>

#include <osgUtil/Tesselator>
#include <osgUtil/TransformCallback>
#include <osgUtil/CullVisitor>

#include <osgGA/TrackballManipulator>
#include <osgProducer/Viewer>
#include <osgDB/ReadFile>

#include <osgSim/ScalarsToColors>
#include <osgSim/ColorRange>
#include <osgSim/ScalarBar>

#include <sstream>
#include <math.h>

using namespace osgSim;
using osgSim::ScalarBar;

osg::Node* createScalarBar()
{
#if 1
    //ScalarsToColors* stc = new ScalarsToColors(0.0f,1.0f);
    //ScalarBar* sb = new ScalarBar(2,3,stc,"STC_ScalarBar");

    // Create a custom color set
    std::vector<osg::Vec4> cs;
    cs.push_back(osg::Vec4(1.0f,0.0f,0.0f,1.0f));   // R
    cs.push_back(osg::Vec4(0.0f,1.0f,0.0f,1.0f));   // G
    cs.push_back(osg::Vec4(1.0f,1.0f,0.0f,1.0f));   // G
    cs.push_back(osg::Vec4(0.0f,0.0f,1.0f,1.0f));   // B
    cs.push_back(osg::Vec4(0.0f,1.0f,1.0f,1.0f));   // R

    // Create a custom scalar printer
    struct MyScalarPrinter: public ScalarBar::ScalarPrinter
    {
        std::string printScalar(float scalar)
        {
            std::cout<<"In MyScalarPrinter::printScalar"<<std::endl;
            if(scalar==0.0f) return ScalarBar::ScalarPrinter::printScalar(scalar)+" Bottom";
            else if(scalar==0.5f) return ScalarBar::ScalarPrinter::printScalar(scalar)+" Middle";
            else if(scalar==1.0f) return ScalarBar::ScalarPrinter::printScalar(scalar)+" Top";
            else return ScalarBar::ScalarPrinter::printScalar(scalar);
        }
    };

    ColorRange* cr = new ColorRange(0.0f,1.0f,cs);
    ScalarBar* sb = new ScalarBar(20, 11, cr, "ScalarBar", ScalarBar::VERTICAL, 0.1f, new MyScalarPrinter);
    sb->setScalarPrinter(new MyScalarPrinter);

    return sb;
#else
    ScalarBar *sb = new ScalarBar;
    ScalarBar::TextProperties tp;
    tp._fontFile = "fonts/times.ttf";

    sb->setTextProperties(tp);

    return sb;
#endif

}

osg::Node * createScalarBar_HUD()
{
    osgSim::ScalarBar * geode = new osgSim::ScalarBar;
    osgSim::ScalarBar::TextProperties tp;
    tp._fontFile = "fonts/times.ttf";
    geode->setTextProperties(tp);
    osg::StateSet * stateset = geode->getOrCreateStateSet();
    stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);

    stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
    stateset->setRenderBinDetails(11, "RenderBin");

    osg::MatrixTransform * modelview = new osg::MatrixTransform;
    modelview->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
    osg::Matrixd matrix(osg::Matrixd::scale(1000,1000,1000) * osg::Matrixd::translate(120,10,0)); // I've played with these values a lot and it seems to work, but I have no idea why
    modelview->setMatrix(matrix);
    modelview->addChild(geode);

    osg::Projection * projection = new osg::Projection;
    projection->setMatrix(osg::Matrix::ortho2D(0,1280,0,1024)); // or whatever the OSG window res is
    projection->addChild(modelview);

    return projection; //make sure you delete the return sb line
}

int main( int argc, char **argv )
{
    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);

    // set up the usage document, in case we need to print out how to use this program.
    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates both text, animation and billboard via custom transform to create the OpenSceneGraph logo..");
    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
    arguments.getApplicationUsage()->addCommandLineOption("ps","Render the Professional Services logo");

    // construct the viewer.
    osgProducer::Viewer viewer(arguments);

    // set up the value with sensible default event handlers.
    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);

    // get details on keyboard and mouse bindings used by the viewer.
    viewer.getUsage(*arguments.getApplicationUsage());

    // if user request help write it out to cout.
    if (arguments.read("-h") || arguments.read("--help"))
    {
        arguments.getApplicationUsage()->write(std::cout);
        return 1;
    }

    // any option left unread are converted into errors to write out later.
    arguments.reportRemainingOptionsAsUnrecognized();

    // report any errors if they have occured when parsing the program aguments.
    if (arguments.errors())
    {
        arguments.writeErrorMessages(std::cout);
        return 1;
    }

    osg::Group* group = new osg::Group;
    group->addChild(createScalarBar());
    group->addChild(createScalarBar_HUD());

    // add model to viewer.
    viewer.setSceneData( group );

    // create the windows and run the threads.
    viewer.realize();

    while( !viewer.done() )
    {
        // wait for all cull and draw threads to complete.
        viewer.sync();

        // update the scene by traversing it with the the update visitor which will
        // call all node update callbacks and animations.
        viewer.update();

        // fire off the cull and draw traversals of the scene.
        viewer.frame();
    }

    // wait for all cull and draw threads to complete before exit.
    viewer.sync();

    return 0;
}
<commit_msg>Added setCullingActive false to the absolute transform.<commit_after>#include <osg/Geode>
#include <osg/ShapeDrawable>
#include <osg/Material>
#include <osg/Texture2D>
#include <osg/MatrixTransform>
#include <osg/PositionAttitudeTransform>
#include <osg/BlendFunc>
#include <osg/ClearNode>
#include <osg/Projection>

#include <osgUtil/Tesselator>
#include <osgUtil/TransformCallback>
#include <osgUtil/CullVisitor>

#include <osgGA/TrackballManipulator>
#include <osgProducer/Viewer>
#include <osgDB/ReadFile>

#include <osgSim/ScalarsToColors>
#include <osgSim/ColorRange>
#include <osgSim/ScalarBar>

#include <sstream>
#include <math.h>

using namespace osgSim;
using osgSim::ScalarBar;

osg::Node* createScalarBar()
{
#if 1
    //ScalarsToColors* stc = new ScalarsToColors(0.0f,1.0f);
    //ScalarBar* sb = new ScalarBar(2,3,stc,"STC_ScalarBar");

    // Create a custom color set
    std::vector<osg::Vec4> cs;
    cs.push_back(osg::Vec4(1.0f,0.0f,0.0f,1.0f));   // R
    cs.push_back(osg::Vec4(0.0f,1.0f,0.0f,1.0f));   // G
    cs.push_back(osg::Vec4(1.0f,1.0f,0.0f,1.0f));   // G
    cs.push_back(osg::Vec4(0.0f,0.0f,1.0f,1.0f));   // B
    cs.push_back(osg::Vec4(0.0f,1.0f,1.0f,1.0f));   // R

    // Create a custom scalar printer
    struct MyScalarPrinter: public ScalarBar::ScalarPrinter
    {
        std::string printScalar(float scalar)
        {
            std::cout<<"In MyScalarPrinter::printScalar"<<std::endl;
            if(scalar==0.0f) return ScalarBar::ScalarPrinter::printScalar(scalar)+" Bottom";
            else if(scalar==0.5f) return ScalarBar::ScalarPrinter::printScalar(scalar)+" Middle";
            else if(scalar==1.0f) return ScalarBar::ScalarPrinter::printScalar(scalar)+" Top";
            else return ScalarBar::ScalarPrinter::printScalar(scalar);
        }
    };

    ColorRange* cr = new ColorRange(0.0f,1.0f,cs);
    ScalarBar* sb = new ScalarBar(20, 11, cr, "ScalarBar", ScalarBar::VERTICAL, 0.1f, new MyScalarPrinter);
    sb->setScalarPrinter(new MyScalarPrinter);

    return sb;
#else
    ScalarBar *sb = new ScalarBar;
    ScalarBar::TextProperties tp;
    tp._fontFile = "fonts/times.ttf";

    sb->setTextProperties(tp);

    return sb;
#endif

}

osg::Node * createScalarBar_HUD()
{
    osgSim::ScalarBar * geode = new osgSim::ScalarBar;
    osgSim::ScalarBar::TextProperties tp;
    tp._fontFile = "fonts/times.ttf";
    geode->setTextProperties(tp);
    osg::StateSet * stateset = geode->getOrCreateStateSet();
    stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);

    stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
    stateset->setRenderBinDetails(11, "RenderBin");

    osg::MatrixTransform * modelview = new osg::MatrixTransform;
    modelview->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
    modelview->setCullingActive(false);
    osg::Matrixd matrix(osg::Matrixd::scale(1000,1000,1000) * osg::Matrixd::translate(120,10,0)); // I've played with these values a lot and it seems to work, but I have no idea why
    modelview->setMatrix(matrix);
    modelview->addChild(geode);

    osg::Projection * projection = new osg::Projection;
    projection->setMatrix(osg::Matrix::ortho2D(0,1280,0,1024)); // or whatever the OSG window res is
    projection->addChild(modelview);

    return projection; //make sure you delete the return sb line
}

int main( int argc, char **argv )
{
    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);

    // set up the usage document, in case we need to print out how to use this program.
    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates both text, animation and billboard via custom transform to create the OpenSceneGraph logo..");
    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
    arguments.getApplicationUsage()->addCommandLineOption("ps","Render the Professional Services logo");

    // construct the viewer.
    osgProducer::Viewer viewer(arguments);

    // set up the value with sensible default event handlers.
    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);

    // get details on keyboard and mouse bindings used by the viewer.
    viewer.getUsage(*arguments.getApplicationUsage());

    // if user request help write it out to cout.
    if (arguments.read("-h") || arguments.read("--help"))
    {
        arguments.getApplicationUsage()->write(std::cout);
        return 1;
    }

    // any option left unread are converted into errors to write out later.
    arguments.reportRemainingOptionsAsUnrecognized();

    // report any errors if they have occured when parsing the program aguments.
    if (arguments.errors())
    {
        arguments.writeErrorMessages(std::cout);
        return 1;
    }

    osg::Group* group = new osg::Group;
    group->addChild(createScalarBar());
    group->addChild(createScalarBar_HUD());

    // add model to viewer.
    viewer.setSceneData( group );

    // create the windows and run the threads.
    viewer.realize();

    while( !viewer.done() )
    {

        // wait for all cull and draw threads to complete.
        viewer.sync();

        // update the scene by traversing it with the the update visitor which will
        // call all node update callbacks and animations.
        viewer.update();

        // fire off the cull and draw traversals of the scene.
        viewer.frame();
    }

    // wait for all cull and draw threads to complete before exit.
    viewer.sync();

    return 0;
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// UniformsBenchmark:
//   Performance test for setting uniform data.
//

#include "ANGLEPerfTest.h"

#include <iostream>
#include <random>
#include <sstream>

#include "Matrix.h"
#include "shader_utils.h"

using namespace angle;

namespace
{

// Controls when we call glUniform, if the data is the same as last frame.
enum DataMode
{
    UPDATE,
    REPEAT,
};

// TODO(jmadill): Use an ANGLE enum for this?
enum DataType
{
    VEC4,
    MAT4,
};

struct UniformsParams final : public RenderTestParams
{
    UniformsParams()
    {
        // Common default params
        majorVersion = 2;
        minorVersion = 0;
        windowWidth  = 720;
        windowHeight = 720;
    }

    std::string suffix() const override;
    size_t numVertexUniforms   = 200;
    size_t numFragmentUniforms = 200;

    DataType dataType = DataType::VEC4;
    DataMode dataMode = DataMode::REPEAT;

    // static parameters
    size_t iterations = 4;
};

std::ostream &operator<<(std::ostream &os, const UniformsParams &params)
{
    os << params.suffix().substr(1);
    return os;
}

std::string UniformsParams::suffix() const
{
    std::stringstream strstr;

    strstr << RenderTestParams::suffix();

    if (dataType == DataType::VEC4)
    {
        strstr << "_" << numVertexUniforms << "_vertex_uniforms";
        strstr << "_" << numFragmentUniforms << "_fragment_uniforms";
    }
    else if (dataMode == DataMode::REPEAT)
    {
        strstr << "_matrix_repeating";
    }
    else
    {
        strstr << "_matrix_updating";
    }

    return strstr.str();
}

class UniformsBenchmark : public ANGLERenderTest,
                          public ::testing::WithParamInterface<UniformsParams>
{
  public:
    UniformsBenchmark();

    void initializeBenchmark() override;
    void destroyBenchmark() override;
    void drawBenchmark() override;

  private:
    void initShaders();
    void initVertexBuffer();
    void initTextures();

    GLuint mProgram;
    std::vector<GLuint> mUniformLocations;
    std::vector<Matrix4> mMatrixData[2];
};

std::vector<Matrix4> GenMatrixData(size_t count, int parity)
{
    std::vector<Matrix4> data;

    // Very simple matrix data allocation scheme.
    for (size_t index = 0; index < count; ++index)
    {
        Matrix4 mat;
        for (int row = 0; row < 4; ++row)
        {
            for (int col = 0; col < 4; ++col)
            {
                mat.data[row * 4 + col] = (row * col + parity) % 2 == 0 ? 1.0f : -1.0f;
            }
        }

        data.push_back(mat);
    }

    return data;
}

UniformsBenchmark::UniformsBenchmark() : ANGLERenderTest("Uniforms", GetParam()), mProgram(0u)
{
}

void UniformsBenchmark::initializeBenchmark()
{
    const auto &params = GetParam();

    ASSERT_GT(params.iterations, 0u);

    // Verify the uniform counts are within the limits
    GLint maxVertexUniformVectors, maxFragmentUniformVectors;
    glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxVertexUniformVectors);
    glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxFragmentUniformVectors);

    bool isMatrix = params.dataType == DataType::MAT4;

    GLint numVertexUniformVectors =
        static_cast<GLint>(params.numVertexUniforms) * (isMatrix ? 4 : 1);
    GLint numFragmentUniformVectors =
        static_cast<GLint>(params.numFragmentUniforms) * (isMatrix ? 4 : 1);

    if (numVertexUniformVectors > maxVertexUniformVectors)
    {
        FAIL() << "Vertex uniform vector count (" << numVertexUniformVectors << ")"
               << " exceeds maximum vertex uniform vector count: " << maxVertexUniformVectors
               << std::endl;
    }
    if (numFragmentUniformVectors > maxFragmentUniformVectors)
    {
        FAIL() << "Fragment uniform vector count (" << numFragmentUniformVectors << ")"
               << " exceeds maximum fragment uniform vector count: " << maxFragmentUniformVectors
               << std::endl;
    }

    initShaders();
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());

    if (isMatrix)
    {
        size_t count = params.numVertexUniforms + params.numFragmentUniforms;

        mMatrixData[0] = GenMatrixData(count, 0);
        if (params.dataMode == DataMode::REPEAT)
        {
            mMatrixData[1] = GenMatrixData(count, 0);
        }
        else
        {
            mMatrixData[1] = GenMatrixData(count, 1);
        }
    }

    ASSERT_GL_NO_ERROR();
}

std::string GetUniformLocationName(size_t idx, bool vertexShader)
{
    std::stringstream strstr;
    strstr << (vertexShader ? "vs" : "fs") << "_u_" << idx;
    return strstr.str();
}

void UniformsBenchmark::initShaders()
{
    const auto &params = GetParam();
    bool isMatrix      = (params.dataType == DataType::MAT4);

    std::stringstream vstrstr;
    vstrstr << "precision mediump float;\n";
    std::string typeString  = isMatrix ? "mat4" : "vec4";
    std::string constVector = "const vec4 one = vec4(1, 1, 1, 1);\n";

    if (isMatrix)
    {
        vstrstr << constVector;
    }

    for (size_t i = 0; i < params.numVertexUniforms; i++)
    {
        vstrstr << "uniform " << typeString << " " << GetUniformLocationName(i, true) << ";\n";
    }

    vstrstr << "void main()\n"
               "{\n"
               "    gl_Position = vec4(0, 0, 0, 0);\n";
    for (size_t i = 0; i < params.numVertexUniforms; i++)
    {
        vstrstr << "    gl_Position += " << GetUniformLocationName(i, true);
        if (isMatrix)
        {
            vstrstr << " * one";
        }
        vstrstr << ";\n";
    }
    vstrstr << "}";

    std::stringstream fstrstr;
    fstrstr << "precision mediump float;\n";

    if (isMatrix)
    {
        fstrstr << constVector;
    }

    for (size_t i = 0; i < params.numFragmentUniforms; i++)
    {
        fstrstr << "uniform " << typeString << " " << GetUniformLocationName(i, false) << ";\n";
    }
    fstrstr << "void main()\n"
               "{\n"
               "    gl_FragColor = vec4(0, 0, 0, 0);\n";
    for (size_t i = 0; i < params.numFragmentUniforms; i++)
    {
        fstrstr << "    gl_FragColor += " << GetUniformLocationName(i, false);
        if (isMatrix)
        {
            fstrstr << " * one";
        }
        fstrstr << ";\n";
    }
    fstrstr << "}";

    mProgram = CompileProgram(vstrstr.str(), fstrstr.str());
    ASSERT_NE(0u, mProgram);

    for (size_t i = 0; i < params.numVertexUniforms; ++i)
    {
        GLint location = glGetUniformLocation(mProgram, GetUniformLocationName(i, true).c_str());
        ASSERT_NE(-1, location);
        mUniformLocations.push_back(location);
    }
    for (size_t i = 0; i < params.numFragmentUniforms; ++i)
    {
        GLint location = glGetUniformLocation(mProgram, GetUniformLocationName(i, false).c_str());
        ASSERT_NE(-1, location);
        mUniformLocations.push_back(location);
    }

    // Use the program object
    glUseProgram(mProgram);
}

void UniformsBenchmark::destroyBenchmark()
{
    glDeleteProgram(mProgram);
}

void UniformsBenchmark::drawBenchmark()
{
    const auto &params = GetParam();

    size_t frameIndex = 0;

    for (size_t it = 0; it < params.iterations; ++it, frameIndex = (frameIndex == 0 ? 1 : 0))
    {
        for (size_t uniform = 0; uniform < mUniformLocations.size(); ++uniform)
        {
            if (params.dataType == DataType::MAT4)
            {
                glUniformMatrix4fv(mUniformLocations[uniform], 1, GL_FALSE,
                                   mMatrixData[frameIndex][uniform].data);
            }
            else
            {
                float value = static_cast<float>(uniform);
                glUniform4f(mUniformLocations[uniform], value, value, value, value);
            }
        }

        glDrawArrays(GL_TRIANGLES, 0, 3);
    }

    ASSERT_GL_NO_ERROR();
}

using namespace egl_platform;

UniformsParams VectorUniforms(const EGLPlatformParameters &egl)
{
    UniformsParams params;
    params.eglParameters = egl;
    return params;
}

UniformsParams MatrixUniforms(const EGLPlatformParameters &egl, DataMode dataMode)
{
    UniformsParams params;
    params.eglParameters = egl;
    params.dataType      = DataType::MAT4;
    params.dataMode      = dataMode;

    // Reduce the number of uniforms to fit within smaller upper limis on some configs.
    params.numVertexUniforms   = 100;
    params.numFragmentUniforms = 100;

    return params;
}

}  // anonymous namespace

TEST_P(UniformsBenchmark, Run)
{
    run();
}

ANGLE_INSTANTIATE_TEST(UniformsBenchmark,
                       VectorUniforms(D3D11()),
                       VectorUniforms(D3D9()),
                       VectorUniforms(OPENGL()),
                       MatrixUniforms(D3D11(), DataMode::REPEAT),
                       MatrixUniforms(D3D11(), DataMode::UPDATE),
                       MatrixUniforms(OPENGL(), DataMode::REPEAT),
                       MatrixUniforms(OPENGL(), DataMode::UPDATE));
<commit_msg>Expand Uniforms perf test.<commit_after>//
// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// UniformsBenchmark:
//   Performance test for setting uniform data.
//

#include "ANGLEPerfTest.h"

#include <iostream>
#include <random>
#include <sstream>

#include "Matrix.h"
#include "shader_utils.h"

using namespace angle;

namespace
{

// Controls when we call glUniform, if the data is the same as last frame.
enum DataMode
{
    UPDATE,
    REPEAT,
};

// TODO(jmadill): Use an ANGLE enum for this?
enum DataType
{
    VEC4,
    MAT4,
};

struct UniformsParams final : public RenderTestParams
{
    UniformsParams()
    {
        // Common default params
        majorVersion = 2;
        minorVersion = 0;
        windowWidth  = 720;
        windowHeight = 720;
    }

    std::string suffix() const override;
    size_t numVertexUniforms   = 200;
    size_t numFragmentUniforms = 200;

    DataType dataType = DataType::VEC4;
    DataMode dataMode = DataMode::REPEAT;

    // static parameters
    size_t iterations = 4;
};

std::ostream &operator<<(std::ostream &os, const UniformsParams &params)
{
    os << params.suffix().substr(1);
    return os;
}

std::string UniformsParams::suffix() const
{
    std::stringstream strstr;

    strstr << RenderTestParams::suffix();

    if (dataType == DataType::VEC4)
    {
        strstr << "_" << (numVertexUniforms + numFragmentUniforms) << "_vec4";
    }
    else
    {
        ASSERT(dataType == DataType::MAT4);
        strstr << "_matrix";
    }

    if (dataMode == DataMode::REPEAT)
    {
        strstr << "_repeating";
    }

    return strstr.str();
}

class UniformsBenchmark : public ANGLERenderTest,
                          public ::testing::WithParamInterface<UniformsParams>
{
  public:
    UniformsBenchmark();

    void initializeBenchmark() override;
    void destroyBenchmark() override;
    void drawBenchmark() override;

  private:
    void initShaders();

    GLuint mProgram;
    std::vector<GLuint> mUniformLocations;
    std::vector<Matrix4> mMatrixData[2];
};

std::vector<Matrix4> GenMatrixData(size_t count, int parity)
{
    std::vector<Matrix4> data;

    // Very simple matrix data allocation scheme.
    for (size_t index = 0; index < count; ++index)
    {
        Matrix4 mat;
        for (int row = 0; row < 4; ++row)
        {
            for (int col = 0; col < 4; ++col)
            {
                mat.data[row * 4 + col] = (row * col + parity) % 2 == 0 ? 1.0f : -1.0f;
            }
        }

        data.push_back(mat);
    }

    return data;
}

UniformsBenchmark::UniformsBenchmark() : ANGLERenderTest("Uniforms", GetParam()), mProgram(0u)
{
}

void UniformsBenchmark::initializeBenchmark()
{
    const auto &params = GetParam();

    ASSERT_GT(params.iterations, 0u);

    // Verify the uniform counts are within the limits
    GLint maxVertexUniformVectors, maxFragmentUniformVectors;
    glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxVertexUniformVectors);
    glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxFragmentUniformVectors);

    bool isMatrix = params.dataType == DataType::MAT4;

    GLint numVertexUniformVectors =
        static_cast<GLint>(params.numVertexUniforms) * (isMatrix ? 4 : 1);
    GLint numFragmentUniformVectors =
        static_cast<GLint>(params.numFragmentUniforms) * (isMatrix ? 4 : 1);

    if (numVertexUniformVectors > maxVertexUniformVectors)
    {
        FAIL() << "Vertex uniform vector count (" << numVertexUniformVectors << ")"
               << " exceeds maximum vertex uniform vector count: " << maxVertexUniformVectors
               << std::endl;
    }
    if (numFragmentUniformVectors > maxFragmentUniformVectors)
    {
        FAIL() << "Fragment uniform vector count (" << numFragmentUniformVectors << ")"
               << " exceeds maximum fragment uniform vector count: " << maxFragmentUniformVectors
               << std::endl;
    }

    initShaders();
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());

    if (isMatrix)
    {
        size_t count = params.numVertexUniforms + params.numFragmentUniforms;

        mMatrixData[0] = GenMatrixData(count, 0);
        if (params.dataMode == DataMode::REPEAT)
        {
            mMatrixData[1] = GenMatrixData(count, 0);
        }
        else
        {
            mMatrixData[1] = GenMatrixData(count, 1);
        }
    }

    ASSERT_GL_NO_ERROR();
}

std::string GetUniformLocationName(size_t idx, bool vertexShader)
{
    std::stringstream strstr;
    strstr << (vertexShader ? "vs" : "fs") << "_u_" << idx;
    return strstr.str();
}

void UniformsBenchmark::initShaders()
{
    const auto &params = GetParam();
    bool isMatrix      = (params.dataType == DataType::MAT4);

    std::stringstream vstrstr;
    vstrstr << "precision mediump float;\n";
    std::string typeString  = isMatrix ? "mat4" : "vec4";
    std::string constVector = "const vec4 one = vec4(1, 1, 1, 1);\n";

    if (isMatrix)
    {
        vstrstr << constVector;
    }

    for (size_t i = 0; i < params.numVertexUniforms; i++)
    {
        vstrstr << "uniform " << typeString << " " << GetUniformLocationName(i, true) << ";\n";
    }

    vstrstr << "void main()\n"
               "{\n"
               "    gl_Position = vec4(0, 0, 0, 0);\n";
    for (size_t i = 0; i < params.numVertexUniforms; i++)
    {
        vstrstr << "    gl_Position += " << GetUniformLocationName(i, true);
        if (isMatrix)
        {
            vstrstr << " * one";
        }
        vstrstr << ";\n";
    }
    vstrstr << "}";

    std::stringstream fstrstr;
    fstrstr << "precision mediump float;\n";

    if (isMatrix)
    {
        fstrstr << constVector;
    }

    for (size_t i = 0; i < params.numFragmentUniforms; i++)
    {
        fstrstr << "uniform " << typeString << " " << GetUniformLocationName(i, false) << ";\n";
    }
    fstrstr << "void main()\n"
               "{\n"
               "    gl_FragColor = vec4(0, 0, 0, 0);\n";
    for (size_t i = 0; i < params.numFragmentUniforms; i++)
    {
        fstrstr << "    gl_FragColor += " << GetUniformLocationName(i, false);
        if (isMatrix)
        {
            fstrstr << " * one";
        }
        fstrstr << ";\n";
    }
    fstrstr << "}";

    mProgram = CompileProgram(vstrstr.str(), fstrstr.str());
    ASSERT_NE(0u, mProgram);

    for (size_t i = 0; i < params.numVertexUniforms; ++i)
    {
        GLint location = glGetUniformLocation(mProgram, GetUniformLocationName(i, true).c_str());
        ASSERT_NE(-1, location);
        mUniformLocations.push_back(location);
    }
    for (size_t i = 0; i < params.numFragmentUniforms; ++i)
    {
        GLint location = glGetUniformLocation(mProgram, GetUniformLocationName(i, false).c_str());
        ASSERT_NE(-1, location);
        mUniformLocations.push_back(location);
    }

    // Use the program object
    glUseProgram(mProgram);
}

void UniformsBenchmark::destroyBenchmark()
{
    glDeleteProgram(mProgram);
}

void UniformsBenchmark::drawBenchmark()
{
    const auto &params = GetParam();

    size_t frameIndex = 0;

    for (size_t it = 0; it < params.iterations; ++it, frameIndex = (frameIndex == 0 ? 1 : 0))
    {
        for (size_t uniform = 0; uniform < mUniformLocations.size(); ++uniform)
        {
            if (params.dataType == DataType::MAT4)
            {
                glUniformMatrix4fv(mUniformLocations[uniform], 1, GL_FALSE,
                                   mMatrixData[frameIndex][uniform].data);
            }
            else
            {
                float value = static_cast<float>(uniform);
                glUniform4f(mUniformLocations[uniform], value, value, value, value);
            }
        }

        glDrawArrays(GL_TRIANGLES, 0, 3);
    }

    ASSERT_GL_NO_ERROR();
}

using namespace egl_platform;

UniformsParams VectorUniforms(const EGLPlatformParameters &egl, DataMode dataMode)
{
    UniformsParams params;
    params.eglParameters = egl;
    params.dataMode      = dataMode;
    return params;
}

UniformsParams MatrixUniforms(const EGLPlatformParameters &egl, DataMode dataMode)
{
    UniformsParams params;
    params.eglParameters = egl;
    params.dataType      = DataType::MAT4;
    params.dataMode      = dataMode;

    // Reduce the number of uniforms to fit within smaller upper limits on some configs.
    params.numVertexUniforms   = 100;
    params.numFragmentUniforms = 100;

    return params;
}

}  // anonymous namespace

TEST_P(UniformsBenchmark, Run)
{
    run();
}

ANGLE_INSTANTIATE_TEST(UniformsBenchmark,
                       VectorUniforms(D3D9(), DataMode::UPDATE),
                       VectorUniforms(D3D11(), DataMode::REPEAT),
                       VectorUniforms(D3D11(), DataMode::UPDATE),
                       VectorUniforms(OPENGL(), DataMode::REPEAT),
                       VectorUniforms(OPENGL(), DataMode::UPDATE),
                       MatrixUniforms(D3D11(), DataMode::REPEAT),
                       MatrixUniforms(D3D11(), DataMode::UPDATE),
                       MatrixUniforms(OPENGL(), DataMode::REPEAT),
                       MatrixUniforms(OPENGL(), DataMode::UPDATE));
<|endoftext|>


<commit_before>#include "DDConfig.h"
#include "DDModel.h"
#include "DDRenderer.h"

DDModel::DDModel():
m_pMesh(NULL),
m_pMeshMaterials(NULL),
m_pMeshTexture(NULL),
m_dwNumMaterials(0L)
{
}

DDModel::DDModel( wchar_t* path )
{
	m_pD3DDevice = DDRenderer::GetInstance()->GetDevice();
	initModel( path );
	SetNormalVector();
}

DDModel::~DDModel()
{
	Cleanup();
}

DDModel* DDModel::Create( wchar_t* filePath )
{
	DDModel* pInstance = new DDModel(filePath);
	return pInstance;
}

bool DDModel::initModel( wchar_t* path )
{
	LPD3DXBUFFER pD3DXMtrlBuffer;

	std::wstring xfilePath = L".\\Resources\\3DModel\\";
	xfilePath.append(path);

	//wcscat_s( resourcePath, MAX_PATH , path );

	HRESULT hr;
	hr = D3DXLoadMeshFromX( xfilePath.c_str(), D3DXMESH_SYSTEMMEM, m_pD3DDevice, NULL, &pD3DXMtrlBuffer, NULL, &m_dwNumMaterials, &m_pMesh );

	if ( FAILED( hr ) )
	{
		// x file loading error
		return false;
	}

	D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
	m_pMeshMaterials = new D3DMATERIAL9[m_dwNumMaterials];
	if ( m_pMeshMaterials == NULL )
	{
		// out of memory
		return false;
	}

	m_pMeshTexture = new LPDIRECT3DTEXTURE9[m_dwNumMaterials];
	if ( m_pMeshTexture == NULL )
	{
		// out of memory
		return false;
	}

	for ( DWORD i = 0; i < m_dwNumMaterials; i++ )
	{
		m_pMeshMaterials[i] = d3dxMaterials[i].MatD3D;

		m_pMeshTexture[i] = NULL;
		if ( d3dxMaterials[i].pTextureFilename != NULL && lstrlenA( d3dxMaterials[i].pTextureFilename ) > 0 )
		{
 			std::string bmpPath = ".\\Resources\\3DModel\\";
			bmpPath.append(d3dxMaterials[i].pTextureFilename );

			if ( FAILED( D3DXCreateTextureFromFileA( m_pD3DDevice, bmpPath.c_str(), &m_pMeshTexture[i] ) ) )
			{
				/*MessageBox( NULL, L"no texture map", L"Meshes.exe", MB_OK );*/
				// no texture error
				return false;
			}
		}
	}

	pD3DXMtrlBuffer->Release();

	return true;
}

bool DDModel::SetNormalVector()
{
	if ( !( m_pMesh->GetFVF() & D3DFVF_NORMAL ) )
	{
		//  ʴٸ ޽ ϰ D3DFVF_NORMAL ߰Ѵ.
		ID3DXMesh* pTempMesh = 0;
		m_pMesh->CloneMeshFVF(
			D3DXMESH_MANAGED,
			m_pMesh->GetFVF() | D3DFVF_NORMAL,  //̰ ߰
			m_pD3DDevice,
			&pTempMesh );

		//  Ѵ.
		if ( FAILED( D3DXComputeNormals( pTempMesh, 0 ) ) )
		{
			return false;
		}

		m_pMesh->Release(); // ޽ Ѵ
		m_pMesh = pTempMesh; // ޽   ޽ Ѵ.
	}

	return true;
}

bool DDModel::Cleanup()
{
	// texture release
	if ( m_pMeshTexture )
	{
		for ( DWORD i = 0; i < m_dwNumMaterials; ++i )
		{
			if ( m_pMeshTexture[i] )
			{
				m_pMeshTexture[i]->Release();
			}
		}
		delete[] m_pMeshTexture;
		m_pMeshTexture = nullptr;
	}

	// mesh release
	if ( m_pMeshMaterials != NULL )
	{
		delete[] m_pMeshMaterials;
		m_pMeshMaterials = nullptr;
	}

	return true;
}

void DDModel::Render()
{
	DDObject::Render();

	for ( DWORD i = 0; i < m_dwNumMaterials; ++i )
	{
		m_pD3DDevice->SetMaterial( &m_pMeshMaterials[i] );
		m_pD3DDevice->SetTexture( 0, m_pMeshTexture[i] );

		m_pMesh->DrawSubset( i );
	}
}

void DDModel::Update( float dTime )
{
	DDObject::Update( dTime );
}
<commit_msg>model ambient light 문제 수정<commit_after>#include "DDConfig.h"
#include "DDModel.h"
#include "DDRenderer.h"

DDModel::DDModel():
m_pMesh(NULL),
m_pMeshMaterials(NULL),
m_pMeshTexture(NULL),
m_dwNumMaterials(0L)
{
}

DDModel::DDModel( wchar_t* path )
{
	m_pD3DDevice = DDRenderer::GetInstance()->GetDevice();
	initModel( path );
	SetNormalVector();
}

DDModel::~DDModel()
{
	Cleanup();
}

DDModel* DDModel::Create( wchar_t* filePath )
{
	DDModel* pInstance = new DDModel(filePath);
	return pInstance;
}

bool DDModel::initModel( wchar_t* path )
{
	LPD3DXBUFFER pD3DXMtrlBuffer;

	std::wstring xfilePath = L".\\Resources\\3DModel\\";
	xfilePath.append(path);

	//wcscat_s( resourcePath, MAX_PATH , path );

	HRESULT hr;
	hr = D3DXLoadMeshFromX( xfilePath.c_str(), D3DXMESH_SYSTEMMEM, m_pD3DDevice, NULL, &pD3DXMtrlBuffer, NULL, &m_dwNumMaterials, &m_pMesh );

	if ( FAILED( hr ) )
	{
		// x file loading error
		return false;
	}

	D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
	m_pMeshMaterials = new D3DMATERIAL9[m_dwNumMaterials];
	if ( m_pMeshMaterials == NULL )
	{
		// out of memory
		return false;
	}

	m_pMeshTexture = new LPDIRECT3DTEXTURE9[m_dwNumMaterials];
	if ( m_pMeshTexture == NULL )
	{
		// out of memory
		return false;
	}

	for ( DWORD i = 0; i < m_dwNumMaterials; i++ )
	{
		m_pMeshMaterials[i] = d3dxMaterials[i].MatD3D;
		m_pMeshMaterials[i].Ambient = m_pMeshMaterials[i].Diffuse;

		m_pMeshTexture[i] = NULL;
		if ( d3dxMaterials[i].pTextureFilename != NULL && lstrlenA( d3dxMaterials[i].pTextureFilename ) > 0 )
		{
 			std::string bmpPath = ".\\Resources\\3DModel\\";
			bmpPath.append(d3dxMaterials[i].pTextureFilename );

			if ( FAILED( D3DXCreateTextureFromFileA( m_pD3DDevice, bmpPath.c_str(), &m_pMeshTexture[i] ) ) )
			{
				/*MessageBox( NULL, L"no texture map", L"Meshes.exe", MB_OK );*/
				// no texture error
				return false;
			}
		}
	}

	pD3DXMtrlBuffer->Release();

	return true;
}

bool DDModel::SetNormalVector()
{
	if ( !( m_pMesh->GetFVF() & D3DFVF_NORMAL ) )
	{
		//  ʴٸ ޽ ϰ D3DFVF_NORMAL ߰Ѵ.
		ID3DXMesh* pTempMesh = 0;
		m_pMesh->CloneMeshFVF(
			D3DXMESH_MANAGED,
			m_pMesh->GetFVF() | D3DFVF_NORMAL,  //̰ ߰
			m_pD3DDevice,
			&pTempMesh );

		//  Ѵ.
		if ( FAILED( D3DXComputeNormals( pTempMesh, 0 ) ) )
		{
			return false;
		}

		m_pMesh->Release(); // ޽ Ѵ
		m_pMesh = pTempMesh; // ޽   ޽ Ѵ.
	}

	return true;
}

bool DDModel::Cleanup()
{
	// texture release
	if ( m_pMeshTexture )
	{
		for ( DWORD i = 0; i < m_dwNumMaterials; ++i )
		{
			if ( m_pMeshTexture[i] )
			{
				m_pMeshTexture[i]->Release();
			}
		}
		delete[] m_pMeshTexture;
		m_pMeshTexture = nullptr;
	}

	// mesh release
	if ( m_pMeshMaterials != NULL )
	{
		delete[] m_pMeshMaterials;
		m_pMeshMaterials = nullptr;
	}

	return true;
}

void DDModel::Render()
{
	DDObject::Render();

	for ( DWORD i = 0; i < m_dwNumMaterials; ++i )
	{
		m_pD3DDevice->SetMaterial( &m_pMeshMaterials[i] );
		m_pD3DDevice->SetTexture( 0, m_pMeshTexture[i] );

		m_pMesh->DrawSubset( i );
	}
}

void DDModel::Update( float dTime )
{
	DDObject::Update( dTime );
}
<|endoftext|>


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

/*
 * Antonin Bas (antonin@barefootnetworks.com)
 *
 */

#include <thread>
#include <mutex>

#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/server/TSimpleServer.h>
#include <thrift/server/TThreadedServer.h>
#include <thrift/transport/TServerSocket.h>
#include <thrift/transport/TBufferTransports.h>
#include <thrift/processor/TMultiplexedProcessor.h>

#include "Standard_server.ipp"
#include "SimplePre_server.ipp"
#include "SimplePreLAG_server.ipp"

using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;

using boost::shared_ptr;

using ::bm_runtime::standard::StandardHandler;
using ::bm_runtime::standard::StandardProcessor;
using ::bm_runtime::simple_pre::SimplePreHandler;
using ::bm_runtime::simple_pre::SimplePreProcessor;
using ::bm_runtime::simple_pre_lag::SimplePreLAGHandler;
using ::bm_runtime::simple_pre_lag::SimplePreLAGProcessor;

namespace bm_runtime {

SwitchWContexts *switch_;
TMultiplexedProcessor *processor_;

namespace {

std::mutex m_ready;
std::condition_variable cv_ready;
bool ready = false;

template<typename T>
bool switch_has_component() {
  return (switch_->get_component<T>() != nullptr);
}

int serve(int port) {
  shared_ptr<TMultiplexedProcessor> processor(new TMultiplexedProcessor());
  processor_ = processor.get();

  shared_ptr<StandardHandler> standard_handler(new StandardHandler(switch_));
  processor->registerProcessor(
    "standard",
    shared_ptr<TProcessor>(new StandardProcessor(standard_handler))
  );

  if(switch_has_component<McSimplePre>()) {
    shared_ptr<SimplePreHandler> simple_pre_handler(new SimplePreHandler(switch_));
    processor->registerProcessor(
      "simple_pre",
      shared_ptr<TProcessor>(new SimplePreProcessor(simple_pre_handler))
    );
  }

  if(switch_has_component<McSimplePreLAG>()) {
    shared_ptr<SimplePreLAGHandler> simple_pre_handler(new SimplePreLAGHandler(switch_));
    processor->registerProcessor(
      "simple_pre_lag",
      shared_ptr<TProcessor>(new SimplePreLAGProcessor(simple_pre_handler))
    );
  }

  shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
  shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
  shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());

  {
    std::unique_lock<std::mutex> lock(m_ready);
    ready = true;
    cv_ready.notify_one();
  }

  TThreadedServer server(processor, serverTransport, transportFactory, protocolFactory);
  server.serve();
  return 0;
}

}

int start_server(SwitchWContexts *sw, int port) {
  switch_ = sw;
  std::thread server_thread(serve, port);
  printf("Thrift server was started\n");
  std::unique_lock<std::mutex> lock(m_ready);
  while(!ready) cv_ready.wait(lock);
  server_thread.detach();
  return 0;
}

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

/*
 * Antonin Bas (antonin@barefootnetworks.com)
 *
 */

#include <thread>
#include <mutex>

#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/server/TSimpleServer.h>
#include <thrift/server/TThreadedServer.h>
#include <thrift/transport/TServerSocket.h>
#include <thrift/transport/TBufferTransports.h>
#include <thrift/processor/TMultiplexedProcessor.h>

#include "Standard_server.ipp"
#include "SimplePre_server.ipp"
#include "SimplePreLAG_server.ipp"

using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;

using boost::shared_ptr;

using ::bm_runtime::standard::StandardHandler;
using ::bm_runtime::standard::StandardProcessor;
using ::bm_runtime::simple_pre::SimplePreHandler;
using ::bm_runtime::simple_pre::SimplePreProcessor;
using ::bm_runtime::simple_pre_lag::SimplePreLAGHandler;
using ::bm_runtime::simple_pre_lag::SimplePreLAGProcessor;

namespace bm_runtime {

SwitchWContexts *switch_;
TMultiplexedProcessor *processor_;

namespace {

std::mutex m_ready;
std::condition_variable cv_ready;
bool ready = false;

template<typename T>
bool switch_has_component() {
  // TODO(antonin): do something more resilient (i.e. per context)
  return (switch_->get_cxt_component<T>(0) != nullptr);
}

int serve(int port) {
  shared_ptr<TMultiplexedProcessor> processor(new TMultiplexedProcessor());
  processor_ = processor.get();

  shared_ptr<StandardHandler> standard_handler(new StandardHandler(switch_));
  processor->registerProcessor(
    "standard",
    shared_ptr<TProcessor>(new StandardProcessor(standard_handler))
  );

  if(switch_has_component<McSimplePre>()) {
    shared_ptr<SimplePreHandler> simple_pre_handler(new SimplePreHandler(switch_));
    processor->registerProcessor(
      "simple_pre",
      shared_ptr<TProcessor>(new SimplePreProcessor(simple_pre_handler))
    );
  }

  if(switch_has_component<McSimplePreLAG>()) {
    shared_ptr<SimplePreLAGHandler> simple_pre_handler(new SimplePreLAGHandler(switch_));
    processor->registerProcessor(
      "simple_pre_lag",
      shared_ptr<TProcessor>(new SimplePreLAGProcessor(simple_pre_handler))
    );
  }

  shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
  shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
  shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());

  {
    std::unique_lock<std::mutex> lock(m_ready);
    ready = true;
    cv_ready.notify_one();
  }

  TThreadedServer server(processor, serverTransport, transportFactory, protocolFactory);
  server.serve();
  return 0;
}

}

int start_server(SwitchWContexts *sw, int port) {
  switch_ = sw;
  std::thread server_thread(serve, port);
  printf("Thrift server was started\n");
  std::unique_lock<std::mutex> lock(m_ready);
  while(!ready) cv_ready.wait(lock);
  server_thread.detach();
  return 0;
}

}
<|endoftext|>


<commit_before>#ifndef SIMDIFY_UTIL_MALLOC_HPP
#define SIMDIFY_UTIL_MALLOC_HPP

#include <type_traits>
#include <exception>
#include <cstdlib>
#include <cstdint>
#include "noexcept.hpp"

namespace simd {

    namespace detail {
#if defined(__GLIBCXX__) && __GLIBCXX__ <= 20150626
        // type_traits is buggered in libstdc++ up until GCC 5
        template <typename T>
        using is_trivially_default_constructible = std::has_trivial_default_constructor<T>;
#else
        template <typename T>
        using is_trivially_default_constructible = std::is_trivially_default_constructible<T>;
#endif

        template <std::size_t x>
        using is_power_of_2 = std::integral_constant<bool, x && (x & (x - 1)) == 0>;
    }

    template <typename T, std::size_t Align>
    T* aligned_malloc(std::size_t count)
    {
        static_assert(detail::is_power_of_2<Align>::value, "alignment must be a power of 2");
        auto size = (sizeof(T) * count) + sizeof(void*) + Align - 1;
        auto orig = std::malloc(size);
        if (orig == nullptr) return nullptr;
        auto aligned = reinterpret_cast<T*>((reinterpret_cast<std::uintptr_t>(orig) + sizeof(void*) + Align - 1) & ~(Align - 1));
        reinterpret_cast<void**>(aligned)[-1] = orig; // save orig right before the start of user data
        return aligned;
    }

    template <typename T>
    void aligned_free(T* aligned)
    {
        if (aligned == nullptr) return;
        auto orig = reinterpret_cast<void**>(aligned)[-1]; // restore orig from right before the start of user data
        std::free(orig);
    }

    struct aligned_deleter {
        template <typename T>
        void operator()(T* ptr) {
            simd::aligned_free(ptr);
        }
    };

    // aligned allocator
    template <typename T, std::size_t Align>
    struct aligned_allocator {
        using value_type = T;

        aligned_allocator() = default;
        template <typename S>
        aligned_allocator(const aligned_allocator<S, Align>&) {}

        T* allocate(std::size_t count) const SIMDIFY_NOEXCEPT {
            return simd::aligned_malloc<T, Align>(count);
        }

        void deallocate(T* ptr, std::size_t) const SIMDIFY_NOEXCEPT {
            simd::aligned_free(ptr);
        }

        // destroy is a no-op if possible
        void destroy(T* ptr) const SIMDIFY_NOEXCEPT_IF(std::is_nothrow_destructible<T>::value) {
            if (!std::is_trivially_destructible<T>::value) {
                ptr->~T();
            }
        }

        // construct without arguments is a no-op if possible
        void construct(T* ptr) const SIMDIFY_NOEXCEPT_IF(std::is_nothrow_constructible<T>::value) {
            if (!detail::is_trivially_default_constructible<T>::value) {
                new (ptr)T;
            }
        }

        // construct with arguments forwarded to placement new
        template <typename A1, typename... A>
        void construct(T* ptr, A1&& a1, A&&... a2) const {
            new (ptr)T(std::forward<A1>(a1), std::forward<A...>(a2)...);
        }

        // default rebind should do just this, doesn't seem to work in MSVC though
        template <typename S>
        struct rebind {
            using other = aligned_allocator<S, Align>;
        };
    };

    // allocator equality
    template <typename T, typename U, std::size_t TS, std::size_t US>
    bool operator==(const aligned_allocator<T, TS>&, const aligned_allocator<U, US>&) { return true; }
    template <typename T, typename U, std::size_t TS, std::size_t US>
    bool operator!=(const aligned_allocator<T, TS>&, const aligned_allocator<U, US>&) { return false; }

    // allocator that throws when used to construct/destroy anything
    template <typename T>
    struct dummy_allocator {
        using value_type = T;

        T* allocate(std::size_t) const { return nullptr; }
        void deallocate(T*, std::size_t) const {}
        void destroy(T*) const { throw std::runtime_error("dummy_allocator::destroy() used"); }

        template <typename... A>
        void construct(T*, A&&...) const { throw std::runtime_error("dummy_allocator::construct() used"); }
    };

    template <typename T, typename U>
    bool operator==(const dummy_allocator<T>&, const dummy_allocator<U>&) { return true; }
    template <typename T, typename U>
    bool operator!=(const dummy_allocator<T>&, const dummy_allocator<U>&) { return false; }

}

#endif // SIMDIFY_UTIL_MALLOC_HPP
<commit_msg>Add support for GCC 4.9.4<commit_after>#ifndef SIMDIFY_UTIL_MALLOC_HPP
#define SIMDIFY_UTIL_MALLOC_HPP

#include <type_traits>
#include <exception>
#include <cstdlib>
#include <cstdint>
#include "noexcept.hpp"

namespace simd {

    namespace detail {
#if defined(__GLIBCXX__) && (__GLIBCXX__ < 20150422 || __GLIBCXX__ == 20150623 || __GLIBCXX__ == 20150626 || __GLIBCXX__ == 20160803)
        // type_traits is buggered in libstdc++ up until GCC 5
        template <typename T>
        using is_trivially_default_constructible = std::has_trivial_default_constructor<T>;
#else
        template <typename T>
        using is_trivially_default_constructible = std::is_trivially_default_constructible<T>;
#endif

        template <std::size_t x>
        using is_power_of_2 = std::integral_constant<bool, x && (x & (x - 1)) == 0>;
    }

    template <typename T, std::size_t Align>
    T* aligned_malloc(std::size_t count)
    {
        static_assert(detail::is_power_of_2<Align>::value, "alignment must be a power of 2");
        auto size = (sizeof(T) * count) + sizeof(void*) + Align - 1;
        auto orig = std::malloc(size);
        if (orig == nullptr) return nullptr;
        auto aligned = reinterpret_cast<T*>((reinterpret_cast<std::uintptr_t>(orig) + sizeof(void*) + Align - 1) & ~(Align - 1));
        reinterpret_cast<void**>(aligned)[-1] = orig; // save orig right before the start of user data
        return aligned;
    }

    template <typename T>
    void aligned_free(T* aligned)
    {
        if (aligned == nullptr) return;
        auto orig = reinterpret_cast<void**>(aligned)[-1]; // restore orig from right before the start of user data
        std::free(orig);
    }

    struct aligned_deleter {
        template <typename T>
        void operator()(T* ptr) {
            simd::aligned_free(ptr);
        }
    };

    // aligned allocator
    template <typename T, std::size_t Align>
    struct aligned_allocator {
        using value_type = T;

        aligned_allocator() = default;
        template <typename S>
        aligned_allocator(const aligned_allocator<S, Align>&) {}

        T* allocate(std::size_t count) const SIMDIFY_NOEXCEPT {
            return simd::aligned_malloc<T, Align>(count);
        }

        void deallocate(T* ptr, std::size_t) const SIMDIFY_NOEXCEPT {
            simd::aligned_free(ptr);
        }

        // destroy is a no-op if possible
        void destroy(T* ptr) const SIMDIFY_NOEXCEPT_IF(std::is_nothrow_destructible<T>::value) {
            if (!std::is_trivially_destructible<T>::value) {
                ptr->~T();
            }
        }

        // construct without arguments is a no-op if possible
        void construct(T* ptr) const SIMDIFY_NOEXCEPT_IF(std::is_nothrow_constructible<T>::value) {
            if (!detail::is_trivially_default_constructible<T>::value) {
                new (ptr)T;
            }
        }

        // construct with arguments forwarded to placement new
        template <typename A1, typename... A>
        void construct(T* ptr, A1&& a1, A&&... a2) const {
            new (ptr)T(std::forward<A1>(a1), std::forward<A...>(a2)...);
        }

        // default rebind should do just this, doesn't seem to work in MSVC though
        template <typename S>
        struct rebind {
            using other = aligned_allocator<S, Align>;
        };
    };

    // allocator equality
    template <typename T, typename U, std::size_t TS, std::size_t US>
    bool operator==(const aligned_allocator<T, TS>&, const aligned_allocator<U, US>&) { return true; }
    template <typename T, typename U, std::size_t TS, std::size_t US>
    bool operator!=(const aligned_allocator<T, TS>&, const aligned_allocator<U, US>&) { return false; }

    // allocator that throws when used to construct/destroy anything
    template <typename T>
    struct dummy_allocator {
        using value_type = T;

        T* allocate(std::size_t) const { return nullptr; }
        void deallocate(T*, std::size_t) const {}
        void destroy(T*) const { throw std::runtime_error("dummy_allocator::destroy() used"); }

        template <typename... A>
        void construct(T*, A&&...) const { throw std::runtime_error("dummy_allocator::construct() used"); }
    };

    template <typename T, typename U>
    bool operator==(const dummy_allocator<T>&, const dummy_allocator<U>&) { return true; }
    template <typename T, typename U>
    bool operator!=(const dummy_allocator<T>&, const dummy_allocator<U>&) { return false; }

}

#endif // SIMDIFY_UTIL_MALLOC_HPP
<|endoftext|>


<commit_before>// Copyright (c) 2013 Craig Henderson
// https://github.com/cdmh/sorting_algorithms
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#include "insertion_sort.h"
#include "merge_sort.h"
#include "heap_sort.h"
#include "quicksort.h"
#include "bubble_sort.h"

#include <algorithm>    // is_sorted
#include <functional>   // greater
#include <vector>
#include <list>
#include <deque>
#include <cassert>
#include <string>
#include <iostream>

template<typename Sort, typename It, typename Pred>
void run_iterator_sort(It it, It ite, Sort sort, Pred pred)
{
    sort(it, ite, pred);
    std::cout << "--> ";
    for (auto each=it; each!=ite; ++each)
        std::cout << *each << " ";
    std::cout << '\n';
    assert(std::is_sorted(it, ite, pred));
}

template<typename Sort, typename C, typename Pred>
void run_container_inplace_sort(Sort sort, C container, Pred pred)
{
    sort(container, pred);
    std::cout << "--> ";
    for (auto each : container)
        std::cout << each << " ";
    std::cout << '\n';
    assert(std::is_sorted(begin(container), end(container), pred));
}

template<typename Sort, typename C, typename Pred>
void run_container_to_container_sort(Sort sort, C container, Pred pred)
{
    C result;
    sort(container, result, pred);

    std::cout << "--> ";
    for (auto each : result)
        std::cout << each << " ";
    std::cout << '\n';

    assert(result.size() == container.size());
    assert(std::is_sorted(begin(result), end(result), pred));
}

template<typename C, typename Pred=std::less<typename C::value_type>>
void test_sorts(C container, Pred pred=Pred())
{
    // we have to specify all the template parameters because otherwise there
    // are name conflicts without the function parameters being specified. In
    // normal usage, the template parameters are deduced automatically;
    //     cdmh::insertion_sort(container, pred);
    //     cdmh::insertion_sort(container.begin(), container.end(), std::greater<typename C::value_type>());
    //     cdmh::merge_sort(container, pred);
    //     ... etc

    // std::sort requires random access iterators, so list & deque are not supported
    std::cout << "std::sort " << container.size() << " elements\n";
    [&pred](std::vector<typename C::value_type> container) {
        run_iterator_sort(container.begin(), container.end(), std::sort<std::vector<typename C::value_type>::iterator, decltype(pred)>, pred);
    }(std::vector<typename C::value_type>(container.begin(), container.end()));

    // std::stable_sort requires random access iterators, so list & deque are not supported
    std::cout << "std::stable_sort " << container.size() << " elements\n";
    [&pred](std::vector<typename C::value_type> container) {
        run_iterator_sort(container.begin(), container.end(), std::stable_sort<std::vector<typename C::value_type>::iterator, decltype(pred)>, pred);
    }(std::vector<typename C::value_type>(container.begin(), container.end()));

    // the heap sort currently uses std::make_heap and std::sort_heap which both require
    // a random access iterator, so only vector is tested here
    std::cout << "Heap Sort " << container.size() << " elements\n";
    run_container_inplace_sort(
        cdmh::heap_sort<std::vector<std::string>, std::less<std::string>, true>,
        std::vector<std::string>{ "the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"},
        std::less<std::string>());

    std::cout << "Merge Sort " << container.size() << " elements\n";
    run_container_to_container_sort(cdmh::merge_sort<std::vector<typename C::value_type>, std::vector<typename C::value_type>, Pred, true>, std::vector<typename C::value_type>(container.begin(), container.end()), pred);
    run_container_to_container_sort(cdmh::merge_sort<std::list  <typename C::value_type>, std::list  <typename C::value_type>, Pred, true>, std::list  <typename C::value_type>(container.begin(), container.end()), pred);
    run_container_to_container_sort(cdmh::merge_sort<std::deque <typename C::value_type>, std::deque <typename C::value_type>, Pred, true>, std::deque <typename C::value_type>(container.begin(), container.end()), pred);

    std::cout << "Inplace Merge Sort " << container.size() << " elements\n";
    run_container_inplace_sort(cdmh::merge_sort<std::vector<typename C::value_type>, Pred, true>, std::vector<typename C::value_type>(container.begin(), container.end()), pred);
    run_container_inplace_sort(cdmh::merge_sort<std::list  <typename C::value_type>, Pred, true>, std::list  <typename C::value_type>(container.begin(), container.end()), pred);
    run_container_inplace_sort(cdmh::merge_sort<std::deque <typename C::value_type>, Pred, true>, std::deque <typename C::value_type>(container.begin(), container.end()), pred);

    std::cout << "Insertion Sort " << container.size() << " elements\n";
    run_container_inplace_sort(cdmh::insertion_sort<std::vector<typename C::value_type>, Pred, true>, std::vector<typename C::value_type>(container.begin(), container.end()), pred);
    run_container_inplace_sort(cdmh::insertion_sort<std::list  <typename C::value_type>, Pred, true>, std::list  <typename C::value_type>(container.begin(), container.end()), pred);
    run_container_inplace_sort(cdmh::insertion_sort<std::deque <typename C::value_type>, Pred, true>, std::deque <typename C::value_type>(container.begin(), container.end()), pred);

    std::cout << "Quicksort " << container.size() << " elements \n";
    run_container_inplace_sort(cdmh::quicksort<std::vector<typename C::value_type>, Pred, true>, std::vector<typename C::value_type>(container.begin(), container.end()), pred);
    run_container_inplace_sort(cdmh::quicksort<std::list  <typename C::value_type>, Pred, true>, std::list  <typename C::value_type>(container.begin(), container.end()), pred);
    run_container_inplace_sort(cdmh::quicksort<std::deque <typename C::value_type>, Pred, true>, std::deque <typename C::value_type>(container.begin(), container.end()), pred);

    std::cout << "Bubble Sort " << container.size() << " elements \n";
    run_container_inplace_sort(cdmh::bubble_sort<std::vector<typename C::value_type>, Pred, true>, std::vector<typename C::value_type>(container.begin(), container.end()), pred);
    run_container_inplace_sort(cdmh::bubble_sort<std::list  <typename C::value_type>, Pred, true>, std::list  <typename C::value_type>(container.begin(), container.end()), pred);
    run_container_inplace_sort(cdmh::bubble_sort<std::deque <typename C::value_type>, Pred, true>, std::deque <typename C::value_type>(container.begin(), container.end()), pred);
}

template<typename C>
void test_all_sorts(C container)
{
    // test sort ascending
    test_sorts(container, std::less<typename C::value_type>());

    // test sort descending
    test_sorts(container, std::greater<typename C::value_type>());
}

int main()
{
    test_all_sorts(std::vector<std::string>{ "the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"});
    test_all_sorts(std::vector<std::string>{ "the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"});
    test_all_sorts(std::vector<int>{});
    test_all_sorts(std::vector<int>{ 3 });
    test_all_sorts(std::vector<int>{ 3, 4, 5, 9, 8, 2, 1, 7, 6 });
    test_all_sorts(std::vector<int>{ 60, 10, 410, 20, 40, 50, 60, 10, 40, 30, 40, 50, 60, 10, 40, 50, 6 });
    test_all_sorts(std::vector<int>{ 10, 20, 30, 40, 510, 20, 50, 60, 10, 60, 130, 10, 20, 30, 40, 50, 60, 140, 10, 20, 30, 40, 50, 60, 1});

    std::vector<int> v{ 10, 20, 30, 40, 510, 20, 50, 60, 10, 60, 130, 10, 20, 30, 40, 50, 60, 140, 10, 20, 30, 40, 50, 60, 1};
    std::sort(v.begin(), v.end());
}
<commit_msg>Added sort stability demonstration<commit_after>// Copyright (c) 2013 Craig Henderson
// https://github.com/cdmh/sorting_algorithms
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#include "insertion_sort.h"
#include "merge_sort.h"
#include "heap_sort.h"
#include "quicksort.h"
#include "bubble_sort.h"

#include <algorithm>    // is_sorted
#include <functional>   // greater
#include <vector>
#include <list>
#include <deque>
#include <cassert>
#include <string>
#include <iostream>

template<typename Sort, typename It, typename Pred>
void run_iterator_sort(It it, It ite, Sort sort, Pred pred)
{
    sort(it, ite, pred);
    std::cout << "--> ";
    for (auto each=it; each!=ite; ++each)
        std::cout << *each << " ";
    std::cout << '\n';
    assert(std::is_sorted(it, ite, pred));
}

template<typename Sort, typename C, typename Pred>
void run_container_inplace_sort(Sort sort, C container, Pred pred)
{
    sort(container, pred);
    std::cout << "--> ";
    for (auto each : container)
        std::cout << each << " ";
    std::cout << '\n';
    assert(std::is_sorted(begin(container), end(container), pred));
}

template<typename Sort, typename C, typename Pred>
void run_container_to_container_sort(Sort sort, C container, Pred pred)
{
    C result;
    sort(container, result, pred);

    std::cout << "--> ";
    for (auto each : result)
        std::cout << each << " ";
    std::cout << '\n';

    assert(result.size() == container.size());
    assert(std::is_sorted(begin(result), end(result), pred));
}

template<typename C, typename Pred=std::less<typename C::value_type>>
void test_sorts(C container, Pred pred=Pred())
{
    // we have to specify all the template parameters because otherwise there
    // are name conflicts without the function parameters being specified. In
    // normal usage, the template parameters are deduced automatically;
    //     cdmh::insertion_sort(container, pred);
    //     cdmh::insertion_sort(container.begin(), container.end(), std::greater<typename C::value_type>());
    //     cdmh::merge_sort(container, pred);
    //     ... etc

    // std::sort requires random access iterators, so list & deque are not supported
    std::cout << "std::sort " << container.size() << " elements\n";
    [&pred](std::vector<typename C::value_type> container) {
        run_iterator_sort(container.begin(), container.end(), std::sort<std::vector<typename C::value_type>::iterator, decltype(pred)>, pred);
    }(std::vector<typename C::value_type>(container.begin(), container.end()));

    // std::stable_sort requires random access iterators, so list & deque are not supported
    std::cout << "std::stable_sort " << container.size() << " elements\n";
    [&pred](std::vector<typename C::value_type> container) {
        run_iterator_sort(container.begin(), container.end(), std::stable_sort<std::vector<typename C::value_type>::iterator, decltype(pred)>, pred);
    }(std::vector<typename C::value_type>(container.begin(), container.end()));

    // the heap sort currently uses std::make_heap and std::sort_heap which both require
    // a random access iterator, so only vector is tested here
    std::cout << "Heap Sort " << container.size() << " elements\n";
    run_container_inplace_sort(cdmh::heap_sort<C, Pred, true>, container, pred);

    std::cout << "Merge Sort " << container.size() << " elements\n";
    run_container_to_container_sort(cdmh::merge_sort<std::vector<typename C::value_type>, std::vector<typename C::value_type>, Pred, true>, std::vector<typename C::value_type>(container.begin(), container.end()), pred);
    run_container_to_container_sort(cdmh::merge_sort<std::list  <typename C::value_type>, std::list  <typename C::value_type>, Pred, true>, std::list  <typename C::value_type>(container.begin(), container.end()), pred);
    run_container_to_container_sort(cdmh::merge_sort<std::deque <typename C::value_type>, std::deque <typename C::value_type>, Pred, true>, std::deque <typename C::value_type>(container.begin(), container.end()), pred);

    std::cout << "Inplace Merge Sort " << container.size() << " elements\n";
    run_container_inplace_sort(cdmh::merge_sort<std::vector<typename C::value_type>, Pred, true>, std::vector<typename C::value_type>(container.begin(), container.end()), pred);
    run_container_inplace_sort(cdmh::merge_sort<std::list  <typename C::value_type>, Pred, true>, std::list  <typename C::value_type>(container.begin(), container.end()), pred);
    run_container_inplace_sort(cdmh::merge_sort<std::deque <typename C::value_type>, Pred, true>, std::deque <typename C::value_type>(container.begin(), container.end()), pred);

    std::cout << "Insertion Sort " << container.size() << " elements\n";
    run_container_inplace_sort(cdmh::insertion_sort<std::vector<typename C::value_type>, Pred, true>, std::vector<typename C::value_type>(container.begin(), container.end()), pred);
    run_container_inplace_sort(cdmh::insertion_sort<std::list  <typename C::value_type>, Pred, true>, std::list  <typename C::value_type>(container.begin(), container.end()), pred);
    run_container_inplace_sort(cdmh::insertion_sort<std::deque <typename C::value_type>, Pred, true>, std::deque <typename C::value_type>(container.begin(), container.end()), pred);

    std::cout << "Quicksort " << container.size() << " elements \n";
    run_container_inplace_sort(cdmh::quicksort<std::vector<typename C::value_type>, Pred, true>, std::vector<typename C::value_type>(container.begin(), container.end()), pred);
    run_container_inplace_sort(cdmh::quicksort<std::list  <typename C::value_type>, Pred, true>, std::list  <typename C::value_type>(container.begin(), container.end()), pred);
    run_container_inplace_sort(cdmh::quicksort<std::deque <typename C::value_type>, Pred, true>, std::deque <typename C::value_type>(container.begin(), container.end()), pred);

    std::cout << "Bubble Sort " << container.size() << " elements \n";
    run_container_inplace_sort(cdmh::bubble_sort<std::vector<typename C::value_type>, Pred, true>, std::vector<typename C::value_type>(container.begin(), container.end()), pred);
    run_container_inplace_sort(cdmh::bubble_sort<std::list  <typename C::value_type>, Pred, true>, std::list  <typename C::value_type>(container.begin(), container.end()), pred);
    run_container_inplace_sort(cdmh::bubble_sort<std::deque <typename C::value_type>, Pred, true>, std::deque <typename C::value_type>(container.begin(), container.end()), pred);
}

template<typename C>
void test_all_sorts(C container)
{
    // test sort ascending
    test_sorts(container, std::less<typename C::value_type>());

    // test sort descending
    test_sorts(container, std::greater<typename C::value_type>());
}

int main()
{
    test_all_sorts(std::vector<std::string>{ "the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog" });
    test_all_sorts(std::vector<std::string>{ "the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog" });
    test_all_sorts(std::vector<int>{});
    test_all_sorts(std::vector<int>{ 3 });
    test_all_sorts(std::vector<int>{ 3, 4, 5, 9, 8, 2, 1, 7, 6 });
    test_all_sorts(std::vector<int>{ 60, 10, 410, 20, 40, 50, 60, 10, 40, 30, 40, 50, 60, 10, 40, 50, 6 });
    test_all_sorts(std::vector<int>{ 10, 20, 30, 40, 510, 20, 50, 60, 10, 60, 130, 10, 20, 30, 40, 50, 60, 140, 10, 20, 30, 40, 50, 60, 1 });

    // shows stability of the sort by comparing doubles as ints
    test_sorts(
        std::vector<double>{ 1.2, 1.1, 0.4, 0.1, 0.9, 3.1, 3.6, 9.4, 9.8, 9.6, 3.2 },
        [](double const &first, double const &second) {
            return int(first)<int(second);
        });

    std::vector<int> v{ 10, 20, 30, 40, 510, 20, 50, 60, 10, 60, 130, 10, 20, 30, 40, 50, 60, 140, 10, 20, 30, 40, 50, 60, 1};
    std::sort(v.begin(), v.end());
}
<|endoftext|>