<commit_before>#include "game.h"

#define LOOKAHEAD 4
#define SACRIFICE_OPTIONS 5
#define OPPONENT_MOVES 5

using namespace std;

// globals
int sacrificeCombinations = factorial(SACRIFICE_OPTIONS) / (factorial(SACRIFICE_OPTIONS - 2) * factorial(2));
stringstream token;
char botId;
char state[16][18];
int roundNum, timebank, myLiveCells, theirLiveCells;

// this just for logging time TODO: remove
auto t = chrono::steady_clock::now();

void game()
{
  string line, command;

  while (getline(cin, line))
  {
    token.clear();
    token.str(line);
    token >> command;

    if (command == "action")
      processAction();
    if (command == "update")
      processUpdate();
    if (command == "settings")
      processSettings();
  }
}

void processAction()
{
  string type, time;
  token >> type;
  token >> time;

  if (type == "move") {
    t = chrono::steady_clock::now(); // TODO: remove
    timebank = stoi(time);
    makeMove();
    chrono::duration<double> diff = chrono::steady_clock::now() - t; // TODO: remove
    cerr << diff.count() * 1000 << "ms used\n"; // TODO: remove
  } else
    cerr << "action type: " << type << " not expected\n";
}

void processUpdate()
{
  string target, field, value;
  token >> target;
  token >> field;
  token >> value;

  if (target == "game") {
    if (field == "round") {
      roundNum = stoi(value);
    }
    if (field == "field") {
      parseState(value);
    }
  } else if (target == "player0" or target == "player1") {
    if (field == "living_cells") {
      if (target[6] == botId)
        myLiveCells = stoi(value);
      else
        theirLiveCells = stoi(value);
    } else if (field != "move")
      cerr << "update playerX field: " << field << " not expected\n";
  } else
    cerr << "update target: " << target << " not expected\n";
}

void processSettings()
{
  string field, value;
  token >> field;
  token >> value;

  if (field == "player_names") {
    if (value != "player0,player1")
      cerr << "settings player_names value: " << value << " not expected\n";
  } else if (field == "your_bot") {
    if (value != "player0" and value != "player1")
      cerr << "settings your_bot value: " << value << " not expected\n";
  } else if (field == "timebank") {
    if (value == "10000")
      timebank = stoi(value);
    else
      cerr << "settings timebank value: " << value << " not expected\n";
  } else if (field == "time_per_move") {
    if (value != "100")
      cerr << "settings time_per_move value: " << value << " not expected\n";
  } else if (field == "field_width") {
    if (value != "18")
      cerr << "settings field_width value: " << value << " not expected\n";
  } else if (field == "field_height") {
    if (value != "16")
      cerr << "settings field_height value: " << value << " not expected\n";
  } else if (field == "max_rounds") {
    if (value != "100")
      cerr << "settings max_rounds value: " << value << " not expected\n";
  } else if (field == "your_botid") {
    if (value == "0" or value == "1")
      botId = value[0];
    else
      cerr << "settings your_botid value: " << value << " not expected\n";
  } else
    cerr << "settings field: " << field << " not expected\n";
}

void parseState(const string &value)
{
  int row = 0;
  int col = 0;
  for (const char& c : value) {
    if (c != ',') {
      state[row][col] = c;
      if (col == 17) {
        col = 0;
        row++;
      } else {
        col++;
      }
    }
  }
}

void makeMove()
{
  int numMoves = 1 + (myLiveCells + theirLiveCells) + (sacrificeCombinations * (288 - myLiveCells - theirLiveCells));

  // TODO: handle less then n of my cells alive for birthing calcs
  node nodes[numMoves];

  addKillNodes(nodes);

  node bestKillNodes[SACRIFICE_OPTIONS];
  findBestKillNodes(nodes, bestKillNodes);

  addPassNode(nodes);

  addBirthNodes(nodes, bestKillNodes);

  // TODO: for the best n nodes, calculate opponent moves and recalculate heuristic, then pick the best of those
  // sort then slice, then 2nd round heuristic, then sort then first
  sort(nodes, nodes + numMoves, nodeCompare);

  // node bestNode = findBestNode(nodes, numMoves);
  node bestNode = nodes[0];

  sendMove(bestNode);
}

void addKillNodes(node nodes[])
{
  int i = 0;
  for (int c = 0; c < 18; c++) {
    for (int r = 0; r < 16; r++) {
      if (state[r][c] != '.') {
        node n;
        n.value = state[r][c];
        n.type = 'k';
        n.target = r * 18 + c;
        copyState(n.state);
        n.state[r][c] = '.';
        calculateNextState(n);
        calculateHeuristic(n);
        nodes[i++] = n;
      }
    }
  }
}

void findBestKillNodes(node nodes[], node bestKillNodes[])
{
  sort(nodes, nodes + myLiveCells + theirLiveCells, nodeCompare);

  int killNodeCount = 0;
  for (int i = 0; i < myLiveCells + theirLiveCells; i++) {
    node n = nodes[i];

    if (n.value == botId) {
      bestKillNodes[killNodeCount] = n;
      killNodeCount++;

      if (killNodeCount == SACRIFICE_OPTIONS) {
        break;
      }
    }
  }
}

void addPassNode(node nodes[])
{
  node n;
  n.type = 'p';
  copyState(n.state);
  calculateNextState(n);
  calculateHeuristic(n);
  nodes[myLiveCells + theirLiveCells] = n;
}

void addBirthNodes(node nodes[], const node bestKillNodes[])
{
  int i = myLiveCells + theirLiveCells + 1;
  for (int x = 0; x < SACRIFICE_OPTIONS - 1; x++) {
    for (int y = x + 1; y < SACRIFICE_OPTIONS; y++) {
      for (int c = 0; c < 18; c++) {
        for (int r = 0; r < 16; r++) {
          if (state[r][c] == '.') {
            node n;
            n.type = 'b';
            n.target = r * 18 + c;
            n.sacrifice1 = bestKillNodes[x].target;
            n.sacrifice2 = bestKillNodes[y].target;
            copyState(n.state);
            n.state[r][c] = botId;
            n.state[n.sacrifice1 / 18][n.sacrifice1 % 18] = '.';
            n.state[n.sacrifice2 / 18][n.sacrifice2 % 18] = '.';
            calculateNextState(n);
            calculateHeuristic(n);
            nodes[i++] = n;
          }
        }
      }
    }
  }
}

node findBestNode(const node nodes[], int nodeCount)
{
  int topHeuristic = -288;
  int topHeuristicIdx = 0;
  for (int i = 0; i < nodeCount; i++) {
    if (nodes[i].heuristicValue > topHeuristic) {
      topHeuristic = nodes[topHeuristicIdx].heuristicValue;
      topHeuristicIdx = i;
    }
  }

  return nodes[topHeuristicIdx];
}

void sendMove(const node &n)
{
  if (n.type == 'p') {
    cout << "pass\n";
  } else if (n.type == 'k') {
    cout << "kill " << coords(n.target) << "\n";
  } else if (n.type == 'b') {
    cout << "birth " << coords(n.target) << " " << coords(n.sacrifice1) << " " << coords(n.sacrifice2) << "\n";
  }
}

void calculateNextState(node &n)
{
  for (int l = 0; l < LOOKAHEAD; l++) {
    int neighbours0[16][18];
    int neighbours1[16][18];

    for (int c = 0; c < 18; c++) {
      for (int r = 0; r < 16; r++) {
        neighbours0[r][c] = 0;
        neighbours1[r][c] = 0;
      }
    }

    for (int c = 0; c < 18; c++) {
      for (int r = 0; r < 16; r++) {
        if (n.state[r][c] == '0') {
          if (c > 0) {
            neighbours0[r][c - 1]++;
            if (r > 0) neighbours0[r - 1][c - 1]++;
            if (r < 15) neighbours0[r + 1][c - 1]++;
          }
          if (c < 17) {
            neighbours0[r][c + 1]++;
            if (r > 0) neighbours0[r - 1][c + 1]++;
            if (r < 15) neighbours0[r + 1][c + 1]++;
          }
          if (r > 0) neighbours0[r - 1][c]++;
          if (r < 15) neighbours0[r + 1][c]++;
        }
        if (n.state[r][c] == '1') {
          if (c > 0) {
            neighbours1[r][c - 1]++;
            if (r > 0) neighbours1[r - 1][c - 1]++;
            if (r < 15) neighbours1[r + 1][c - 1]++;
          }
          if (c < 17) {
            neighbours1[r][c + 1]++;
            if (r > 0) neighbours1[r - 1][c + 1]++;
            if (r < 15) neighbours1[r + 1][c + 1]++;
          }
          if (r > 0) neighbours1[r - 1][c]++;
          if (r < 15) neighbours1[r + 1][c]++;
        }
      }
    }

    int neighbours;
    for (int c = 0; c < 18; c++) {
      for (int r = 0; r < 16; r++) {
        neighbours = neighbours0[r][c] + neighbours1[r][c];
        if (n.state[r][c] == '.' and neighbours == 3) {
          n.state[r][c] = (neighbours0[r][c] > neighbours1[r][c]) ?  '0' : '1';
        } else if (n.state[r][c] != '.' and (neighbours < 2 or neighbours > 3)) {
          n.state[r][c] = '.';
        }
      }
    }
  }
}

void calculateHeuristic(node &n)
{
  int cellCount0 = 0;
  int cellCount1 = 0;

  // TODO: consider the number of opponent cells alive to increase aggression when they are low
  for (int c = 0; c < 18; c++) {
    for (int r = 0; r < 16; r++) {
      if (n.state[r][c] == '0') {
        cellCount0++;
      } else if (n.state[r][c] == '1') {
        cellCount1++;
      }
    }
  }

  if (botId == '0') {
    if (cellCount0 == 0) {
      n.heuristicValue = -288;
    } else if (cellCount1 == 0) {
      n.heuristicValue = 288;
    } else {
      n.heuristicValue = cellCount0 - cellCount1;
    }
  } else if (botId == '1') {
    if (cellCount1 == 0) {
      n.heuristicValue = -288;
    } else if (cellCount0 == 0) {
      n.heuristicValue = 288;
    } else {
      n.heuristicValue = cellCount1 - cellCount0;
    }
  }
}

// utility functions
int factorial(int x, int result) {
  return (x == 1) ? result : factorial(x - 1, x * result);
}

string coords(int cellIdx)
{
  stringstream ss;
  ss << (cellIdx % 18) << "," << cellIdx / 18;
  return ss.str();
}

void copyState(const char source[][18], char target[][18])
{
  for (int r = 0; r < 16; r++) {
    for (int c = 0; c < 18; c++) {
      target[r][c] = source[r][c];
    }
  }
}

bool nodeCompare(node lhs, node rhs)
{
  // sort descending
  return lhs.heuristicValue > rhs.heuristicValue;
}

// debug functions
void setBotId(const char id)
{
  botId = id;
}
<commit_msg>calculateNextState takes lookahead as an arg<commit_after>#include "game.h"

#define LOOKAHEAD 4
#define SACRIFICE_OPTIONS 5
#define OPPONENT_MOVES 5

using namespace std;

// globals
int sacrificeCombinations = factorial(SACRIFICE_OPTIONS) / (factorial(SACRIFICE_OPTIONS - 2) * factorial(2));
stringstream token;
char botId;
char state[16][18];
int roundNum, timebank, myLiveCells, theirLiveCells;

// this just for logging time TODO: remove
auto t = chrono::steady_clock::now();

void game()
{
  string line, command;

  while (getline(cin, line))
  {
    token.clear();
    token.str(line);
    token >> command;

    if (command == "action")
      processAction();
    if (command == "update")
      processUpdate();
    if (command == "settings")
      processSettings();
  }
}

void processAction()
{
  string type, time;
  token >> type;
  token >> time;

  if (type == "move") {
    t = chrono::steady_clock::now(); // TODO: remove
    timebank = stoi(time);
    makeMove();
    chrono::duration<double> diff = chrono::steady_clock::now() - t; // TODO: remove
    cerr << diff.count() * 1000 << "ms used\n"; // TODO: remove
  } else
    cerr << "action type: " << type << " not expected\n";
}

void processUpdate()
{
  string target, field, value;
  token >> target;
  token >> field;
  token >> value;

  if (target == "game") {
    if (field == "round") {
      roundNum = stoi(value);
    }
    if (field == "field") {
      parseState(value);
    }
  } else if (target == "player0" or target == "player1") {
    if (field == "living_cells") {
      if (target[6] == botId)
        myLiveCells = stoi(value);
      else
        theirLiveCells = stoi(value);
    } else if (field != "move")
      cerr << "update playerX field: " << field << " not expected\n";
  } else
    cerr << "update target: " << target << " not expected\n";
}

void processSettings()
{
  string field, value;
  token >> field;
  token >> value;

  if (field == "player_names") {
    if (value != "player0,player1")
      cerr << "settings player_names value: " << value << " not expected\n";
  } else if (field == "your_bot") {
    if (value != "player0" and value != "player1")
      cerr << "settings your_bot value: " << value << " not expected\n";
  } else if (field == "timebank") {
    if (value == "10000")
      timebank = stoi(value);
    else
      cerr << "settings timebank value: " << value << " not expected\n";
  } else if (field == "time_per_move") {
    if (value != "100")
      cerr << "settings time_per_move value: " << value << " not expected\n";
  } else if (field == "field_width") {
    if (value != "18")
      cerr << "settings field_width value: " << value << " not expected\n";
  } else if (field == "field_height") {
    if (value != "16")
      cerr << "settings field_height value: " << value << " not expected\n";
  } else if (field == "max_rounds") {
    if (value != "100")
      cerr << "settings max_rounds value: " << value << " not expected\n";
  } else if (field == "your_botid") {
    if (value == "0" or value == "1")
      botId = value[0];
    else
      cerr << "settings your_botid value: " << value << " not expected\n";
  } else
    cerr << "settings field: " << field << " not expected\n";
}

void parseState(const string &value)
{
  int row = 0;
  int col = 0;
  for (const char& c : value) {
    if (c != ',') {
      state[row][col] = c;
      if (col == 17) {
        col = 0;
        row++;
      } else {
        col++;
      }
    }
  }
}

void makeMove()
{
  int numMoves = 1 + (myLiveCells + theirLiveCells) + (sacrificeCombinations * (288 - myLiveCells - theirLiveCells));

  // TODO: handle less then n of my cells alive for birthing calcs
  node nodes[numMoves];

  addKillNodes(nodes);

  node bestKillNodes[SACRIFICE_OPTIONS];
  findBestKillNodes(nodes, bestKillNodes);

  addPassNode(nodes);

  addBirthNodes(nodes, bestKillNodes);

  // TODO: for the best n nodes, calculate opponent moves and recalculate heuristic, then pick the best of those
  // sort then slice, then 2nd round heuristic, then sort then first
  sort(nodes, nodes + numMoves, nodeCompare);

  // node bestNode = findBestNode(nodes, numMoves);
  node bestNode = nodes[0];

  sendMove(bestNode);
}

void addKillNodes(node nodes[])
{
  int i = 0;
  for (int c = 0; c < 18; c++) {
    for (int r = 0; r < 16; r++) {
      if (state[r][c] != '.') {
        node n;
        n.value = state[r][c];
        n.type = 'k';
        n.target = r * 18 + c;
        copyState(n.state);
        n.state[r][c] = '.';
        calculateNextState(n);
        calculateHeuristic(n);
        nodes[i++] = n;
      }
    }
  }
}

void findBestKillNodes(node nodes[], node bestKillNodes[])
{
  sort(nodes, nodes + myLiveCells + theirLiveCells, nodeCompare);

  int killNodeCount = 0;
  for (int i = 0; i < myLiveCells + theirLiveCells; i++) {
    node n = nodes[i];

    if (n.value == botId) {
      bestKillNodes[killNodeCount] = n;
      killNodeCount++;

      if (killNodeCount == SACRIFICE_OPTIONS) {
        break;
      }
    }
  }
}

void addPassNode(node nodes[])
{
  node n;
  n.type = 'p';
  copyState(n.state);
  calculateNextState(n);
  calculateHeuristic(n);
  nodes[myLiveCells + theirLiveCells] = n;
}

void addBirthNodes(node nodes[], const node bestKillNodes[])
{
  int i = myLiveCells + theirLiveCells + 1;
  for (int x = 0; x < SACRIFICE_OPTIONS - 1; x++) {
    for (int y = x + 1; y < SACRIFICE_OPTIONS; y++) {
      for (int c = 0; c < 18; c++) {
        for (int r = 0; r < 16; r++) {
          if (state[r][c] == '.') {
            node n;
            n.type = 'b';
            n.target = r * 18 + c;
            n.sacrifice1 = bestKillNodes[x].target;
            n.sacrifice2 = bestKillNodes[y].target;
            copyState(n.state);
            n.state[r][c] = botId;
            n.state[n.sacrifice1 / 18][n.sacrifice1 % 18] = '.';
            n.state[n.sacrifice2 / 18][n.sacrifice2 % 18] = '.';
            calculateNextState(n);
            calculateHeuristic(n);
            nodes[i++] = n;
          }
        }
      }
    }
  }
}

node findBestNode(const node nodes[], int nodeCount)
{
  int topHeuristic = -288;
  int topHeuristicIdx = 0;
  for (int i = 0; i < nodeCount; i++) {
    if (nodes[i].heuristicValue > topHeuristic) {
      topHeuristic = nodes[topHeuristicIdx].heuristicValue;
      topHeuristicIdx = i;
    }
  }

  return nodes[topHeuristicIdx];
}

void sendMove(const node &n)
{
  if (n.type == 'p') {
    cout << "pass\n";
  } else if (n.type == 'k') {
    cout << "kill " << coords(n.target) << "\n";
  } else if (n.type == 'b') {
    cout << "birth " << coords(n.target) << " " << coords(n.sacrifice1) << " " << coords(n.sacrifice2) << "\n";
  }
}

void calculateNextState(node &n, int lookahead)
{
  for (int l = 0; l < lookahead; l++) {
    int neighbours0[16][18];
    int neighbours1[16][18];

    for (int c = 0; c < 18; c++) {
      for (int r = 0; r < 16; r++) {
        neighbours0[r][c] = 0;
        neighbours1[r][c] = 0;
      }
    }

    for (int c = 0; c < 18; c++) {
      for (int r = 0; r < 16; r++) {
        if (n.state[r][c] == '0') {
          if (c > 0) {
            neighbours0[r][c - 1]++;
            if (r > 0) neighbours0[r - 1][c - 1]++;
            if (r < 15) neighbours0[r + 1][c - 1]++;
          }
          if (c < 17) {
            neighbours0[r][c + 1]++;
            if (r > 0) neighbours0[r - 1][c + 1]++;
            if (r < 15) neighbours0[r + 1][c + 1]++;
          }
          if (r > 0) neighbours0[r - 1][c]++;
          if (r < 15) neighbours0[r + 1][c]++;
        }
        if (n.state[r][c] == '1') {
          if (c > 0) {
            neighbours1[r][c - 1]++;
            if (r > 0) neighbours1[r - 1][c - 1]++;
            if (r < 15) neighbours1[r + 1][c - 1]++;
          }
          if (c < 17) {
            neighbours1[r][c + 1]++;
            if (r > 0) neighbours1[r - 1][c + 1]++;
            if (r < 15) neighbours1[r + 1][c + 1]++;
          }
          if (r > 0) neighbours1[r - 1][c]++;
          if (r < 15) neighbours1[r + 1][c]++;
        }
      }
    }

    int neighbours;
    for (int c = 0; c < 18; c++) {
      for (int r = 0; r < 16; r++) {
        neighbours = neighbours0[r][c] + neighbours1[r][c];
        if (n.state[r][c] == '.' and neighbours == 3) {
          n.state[r][c] = (neighbours0[r][c] > neighbours1[r][c]) ?  '0' : '1';
        } else if (n.state[r][c] != '.' and (neighbours < 2 or neighbours > 3)) {
          n.state[r][c] = '.';
        }
      }
    }
  }
}

void calculateHeuristic(node &n)
{
  int cellCount0 = 0;
  int cellCount1 = 0;

  // TODO: consider the number of opponent cells alive to increase aggression when they are low
  for (int c = 0; c < 18; c++) {
    for (int r = 0; r < 16; r++) {
      if (n.state[r][c] == '0') {
        cellCount0++;
      } else if (n.state[r][c] == '1') {
        cellCount1++;
      }
    }
  }

  if (botId == '0') {
    if (cellCount0 == 0) {
      n.heuristicValue = -288;
    } else if (cellCount1 == 0) {
      n.heuristicValue = 288;
    } else {
      n.heuristicValue = cellCount0 - cellCount1;
    }
  } else if (botId == '1') {
    if (cellCount1 == 0) {
      n.heuristicValue = -288;
    } else if (cellCount0 == 0) {
      n.heuristicValue = 288;
    } else {
      n.heuristicValue = cellCount1 - cellCount0;
    }
  }
}

// utility functions
int factorial(int x, int result) {
  return (x == 1) ? result : factorial(x - 1, x * result);
}

string coords(int cellIdx)
{
  stringstream ss;
  ss << (cellIdx % 18) << "," << cellIdx / 18;
  return ss.str();
}

void copyState(const char source[][18], char target[][18])
{
  for (int r = 0; r < 16; r++) {
    for (int c = 0; c < 18; c++) {
      target[r][c] = source[r][c];
    }
  }
}

bool nodeCompare(node lhs, node rhs)
{
  // sort descending
  return lhs.heuristicValue > rhs.heuristicValue;
}

// debug functions
void setBotId(const char id)
{
  botId = id;
}
<|endoftext|>


<commit_before>#include "core/settings.hpp"
#include "core/tz_glad/glad_context.hpp"
#include "core/debug/assert.hpp"

namespace tz
{
    void RenderSettings::enable_wireframe_mode(bool wireframe) const
    {
        if(wireframe)
        {
            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
            glLineWidth(1.0f);
        }
        else
        {
            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        }
    }

    RenderSettings::CullTarget RenderSettings::get_culling() const
    {
        tz::RenderSettings::CullTarget cull;
        GLint val;
        glGetIntegerv(GL_CULL_FACE, &val);
        if(val == GL_FALSE)
        {
            cull = tz::RenderSettings::CullTarget::Nothing;
        }
        else
        {
            glGetIntegerv(GL_CULL_FACE_MODE, &val);
            switch(val)
            {
                case GL_BACK:
                    cull = tz::RenderSettings::CullTarget::BackFaces;
                break;
                case GL_FRONT:
                    cull = tz::RenderSettings::CullTarget::FrontFaces;
                break;
                case GL_FRONT_AND_BACK:
                    cull = tz::RenderSettings::CullTarget::Both;
                break;
                default:
                    topaz_assert(false, "Could not retrieve current culling mode. Perhaps this needs to be updated?");
                break;
            }
        }
        return cull;
    }

    void RenderSettings::set_culling(tz::RenderSettings::CullTarget culling) const
    {
        if(culling == tz::RenderSettings::CullTarget::Nothing)
        {
            glDisable(GL_CULL_FACE);
            return;
        }
        glEnable(GL_CULL_FACE);
        switch(culling)
        {
            case tz::RenderSettings::CullTarget::BackFaces:
                glCullFace(GL_BACK);
            break;
            case tz::RenderSettings::CullTarget::FrontFaces:
                glCullFace(GL_FRONT);
            break;
            case tz::RenderSettings::CullTarget::Both:
                glCullFace(GL_FRONT_AND_BACK);
            break;
            default:
                topaz_assert(false, "tz::RenderSettings::set_culling(CullTarget): Unknown CullTarget. Garbage enum value?");
            break;
        }
    }

    RenderSettings::DepthTesting RenderSettings::get_depth_testing() const
    {
        GLint val;
        glGetIntegerv(GL_DEPTH_TEST, &val);
        if(val == GL_FALSE)
        {
            return DepthTesting::AlwaysPass;
        }
        glGetIntegerv(GL_DEPTH_FUNC, &val);
        switch(val)
        {
            case GL_NEVER:
                return DepthTesting::NeverPass;
            break;
            case GL_LESS:
                return DepthTesting::PassIfLess;
            break;
            case GL_EQUAL:
                return DepthTesting::PassIfEqual;
            break;
            case GL_LEQUAL:
                return DepthTesting::PassIfLequal;
            break;
            case GL_GREATER:
                return DepthTesting::PassIfGreater;
            break;
            case GL_NOTEQUAL:
                return DepthTesting::PassIfNequal;
            break;
            case GL_GEQUAL:
                return DepthTesting::PassIfGequal;
            break;
            case GL_ALWAYS:
                return DepthTesting::AlwaysPass;
            break;
            default:
                topaz_assert(false, "tz::RenderSettings::get_depth_testing(): Unexpected state. Returning default of DepthTesting::PassIfLess.");
                return DepthTesting::PassIfLess;
            break;
        }
    }

    void RenderSettings::set_depth_testing(DepthTesting depth_testing)
    {
        if(depth_testing == DepthTesting::AlwaysPass)
        {
            glDisable(GL_DEPTH_TEST);
        }
        else
        {
            glEnable(GL_DEPTH_TEST);
            switch(depth_testing)
            {
                case DepthTesting::NeverPass:
                    glDepthFunc(GL_NEVER);
                break;
                case DepthTesting::PassIfLess:
                    glDepthFunc(GL_LESS);
                break;
                case DepthTesting::PassIfEqual:
                    glDepthFunc(GL_EQUAL);
                break;
                case DepthTesting::PassIfLequal:
                    glDepthFunc(GL_LEQUAL);
                break;
                case DepthTesting::PassIfGreater:
                    glDepthFunc(GL_GREATER);
                break;
                case DepthTesting::PassIfNequal:
                    glDepthFunc(GL_NOTEQUAL);
                break;
                case DepthTesting::PassIfGequal:
                    glDepthFunc(GL_GEQUAL);
                break;
                case DepthTesting::AlwaysPass:
                    glDepthFunc(GL_ALWAYS);
                break;
                default:
                    topaz_assert(false, "tz::RenderSettings::set_depth_testing(DepthTesting): Invalid state. Using default of DepthTesting::PassIfLess.");
                    glDepthFunc(GL_LESS);
                break;
            }
        }
    }
}<commit_msg>* Fixed wrong include path in core/settings.cpp. This was actually found by github actions yay!<commit_after>#include "core/settings.hpp"
#include "ext/tz_glad/glad_context.hpp"
#include "core/debug/assert.hpp"

namespace tz
{
    void RenderSettings::enable_wireframe_mode(bool wireframe) const
    {
        if(wireframe)
        {
            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
            glLineWidth(1.0f);
        }
        else
        {
            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        }
    }

    RenderSettings::CullTarget RenderSettings::get_culling() const
    {
        tz::RenderSettings::CullTarget cull;
        GLint val;
        glGetIntegerv(GL_CULL_FACE, &val);
        if(val == GL_FALSE)
        {
            cull = tz::RenderSettings::CullTarget::Nothing;
        }
        else
        {
            glGetIntegerv(GL_CULL_FACE_MODE, &val);
            switch(val)
            {
                case GL_BACK:
                    cull = tz::RenderSettings::CullTarget::BackFaces;
                break;
                case GL_FRONT:
                    cull = tz::RenderSettings::CullTarget::FrontFaces;
                break;
                case GL_FRONT_AND_BACK:
                    cull = tz::RenderSettings::CullTarget::Both;
                break;
                default:
                    topaz_assert(false, "Could not retrieve current culling mode. Perhaps this needs to be updated?");
                break;
            }
        }
        return cull;
    }

    void RenderSettings::set_culling(tz::RenderSettings::CullTarget culling) const
    {
        if(culling == tz::RenderSettings::CullTarget::Nothing)
        {
            glDisable(GL_CULL_FACE);
            return;
        }
        glEnable(GL_CULL_FACE);
        switch(culling)
        {
            case tz::RenderSettings::CullTarget::BackFaces:
                glCullFace(GL_BACK);
            break;
            case tz::RenderSettings::CullTarget::FrontFaces:
                glCullFace(GL_FRONT);
            break;
            case tz::RenderSettings::CullTarget::Both:
                glCullFace(GL_FRONT_AND_BACK);
            break;
            default:
                topaz_assert(false, "tz::RenderSettings::set_culling(CullTarget): Unknown CullTarget. Garbage enum value?");
            break;
        }
    }

    RenderSettings::DepthTesting RenderSettings::get_depth_testing() const
    {
        GLint val;
        glGetIntegerv(GL_DEPTH_TEST, &val);
        if(val == GL_FALSE)
        {
            return DepthTesting::AlwaysPass;
        }
        glGetIntegerv(GL_DEPTH_FUNC, &val);
        switch(val)
        {
            case GL_NEVER:
                return DepthTesting::NeverPass;
            break;
            case GL_LESS:
                return DepthTesting::PassIfLess;
            break;
            case GL_EQUAL:
                return DepthTesting::PassIfEqual;
            break;
            case GL_LEQUAL:
                return DepthTesting::PassIfLequal;
            break;
            case GL_GREATER:
                return DepthTesting::PassIfGreater;
            break;
            case GL_NOTEQUAL:
                return DepthTesting::PassIfNequal;
            break;
            case GL_GEQUAL:
                return DepthTesting::PassIfGequal;
            break;
            case GL_ALWAYS:
                return DepthTesting::AlwaysPass;
            break;
            default:
                topaz_assert(false, "tz::RenderSettings::get_depth_testing(): Unexpected state. Returning default of DepthTesting::PassIfLess.");
                return DepthTesting::PassIfLess;
            break;
        }
    }

    void RenderSettings::set_depth_testing(DepthTesting depth_testing)
    {
        if(depth_testing == DepthTesting::AlwaysPass)
        {
            glDisable(GL_DEPTH_TEST);
        }
        else
        {
            glEnable(GL_DEPTH_TEST);
            switch(depth_testing)
            {
                case DepthTesting::NeverPass:
                    glDepthFunc(GL_NEVER);
                break;
                case DepthTesting::PassIfLess:
                    glDepthFunc(GL_LESS);
                break;
                case DepthTesting::PassIfEqual:
                    glDepthFunc(GL_EQUAL);
                break;
                case DepthTesting::PassIfLequal:
                    glDepthFunc(GL_LEQUAL);
                break;
                case DepthTesting::PassIfGreater:
                    glDepthFunc(GL_GREATER);
                break;
                case DepthTesting::PassIfNequal:
                    glDepthFunc(GL_NOTEQUAL);
                break;
                case DepthTesting::PassIfGequal:
                    glDepthFunc(GL_GEQUAL);
                break;
                case DepthTesting::AlwaysPass:
                    glDepthFunc(GL_ALWAYS);
                break;
                default:
                    topaz_assert(false, "tz::RenderSettings::set_depth_testing(DepthTesting): Invalid state. Using default of DepthTesting::PassIfLess.");
                    glDepthFunc(GL_LESS);
                break;
            }
        }
    }
}<|endoftext|>


<commit_before>#include "archive.hh"
#include "fs-accessor.hh"
#include "store-api.hh"

namespace nix {

struct LocalStoreAccessor : public FSAccessor
{
    ref<Store> store;

    LocalStoreAccessor(ref<Store> store) : store(store) { }

    void assertStore(const Path & path)
    {
        Path storePath = toStorePath(path);
        if (!store->isValidPath(storePath))
            throw Error(format("path ‘%1%’ is not a valid store path") % storePath);
    }

    FSAccessor::Stat stat(const Path & path) override
    {
        assertStore(path);

        struct stat st;
        if (lstat(path.c_str(), &st)) {
            if (errno == ENOENT) return {Type::tMissing, 0, false};
            throw SysError(format("getting status of ‘%1%’") % path);
        }

        if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode))
            throw Error(format("file ‘%1%’ has unsupported type") % path);

        return {
            S_ISREG(st.st_mode) ? Type::tRegular :
            S_ISLNK(st.st_mode) ? Type::tSymlink :
            Type::tDirectory,
            S_ISREG(st.st_mode) ? (uint64_t) st.st_size : 0,
            S_ISREG(st.st_mode) && st.st_mode & S_IXUSR};
    }

    StringSet readDirectory(const Path & path) override
    {
        assertStore(path);

        auto entries = nix::readDirectory(path);

        StringSet res;
        for (auto & entry : entries)
            res.insert(entry.name);

        return res;
    }

    std::string readFile(const Path & path) override
    {
        assertStore(path);
        return nix::readFile(path);
    }

    std::string readLink(const Path & path) override
    {
        assertStore(path);
        return nix::readLink(path);
    }
};

ref<FSAccessor> LocalFSStore::getFSAccessor()
{
    return make_ref<LocalStoreAccessor>(ref<Store>(shared_from_this()));
}

void LocalFSStore::narFromPath(const Path & path, Sink & sink)
{
    if (!isValidPath(path))
        throw Error(format("path ‘%s’ is not valid") % path);
    dumpPath(path, sink);
}

}
<commit_msg>LocalStoreAccessor::stat: Handle ENOTDIR<commit_after>#include "archive.hh"
#include "fs-accessor.hh"
#include "store-api.hh"

namespace nix {

struct LocalStoreAccessor : public FSAccessor
{
    ref<Store> store;

    LocalStoreAccessor(ref<Store> store) : store(store) { }

    void assertStore(const Path & path)
    {
        Path storePath = toStorePath(path);
        if (!store->isValidPath(storePath))
            throw Error(format("path ‘%1%’ is not a valid store path") % storePath);
    }

    FSAccessor::Stat stat(const Path & path) override
    {
        assertStore(path);

        struct stat st;
        if (lstat(path.c_str(), &st)) {
            if (errno == ENOENT || errno == ENOTDIR) return {Type::tMissing, 0, false};
            throw SysError(format("getting status of ‘%1%’") % path);
        }

        if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode))
            throw Error(format("file ‘%1%’ has unsupported type") % path);

        return {
            S_ISREG(st.st_mode) ? Type::tRegular :
            S_ISLNK(st.st_mode) ? Type::tSymlink :
            Type::tDirectory,
            S_ISREG(st.st_mode) ? (uint64_t) st.st_size : 0,
            S_ISREG(st.st_mode) && st.st_mode & S_IXUSR};
    }

    StringSet readDirectory(const Path & path) override
    {
        assertStore(path);

        auto entries = nix::readDirectory(path);

        StringSet res;
        for (auto & entry : entries)
            res.insert(entry.name);

        return res;
    }

    std::string readFile(const Path & path) override
    {
        assertStore(path);
        return nix::readFile(path);
    }

    std::string readLink(const Path & path) override
    {
        assertStore(path);
        return nix::readLink(path);
    }
};

ref<FSAccessor> LocalFSStore::getFSAccessor()
{
    return make_ref<LocalStoreAccessor>(ref<Store>(shared_from_this()));
}

void LocalFSStore::narFromPath(const Path & path, Sink & sink)
{
    if (!isValidPath(path))
        throw Error(format("path ‘%s’ is not valid") % path);
    dumpPath(path, sink);
}

}
<|endoftext|>


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

#include <fftw3.h>
#include "crosscorrelate.h"

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

namespace votca { namespace tools {

/**
    \todo clean implementation!!!
*/
void CrossCorrelate::AutoCorrelate(DataCollection<double>::selection *data, bool average)
{
#ifdef NOFFTW
    throw std::runtime_error("CrossCorrelate::AutoCorrelate is not compiled-in due to disabling of FFTW - recompile libtool with '--with-ffw'");
#else
    size_t N = (*data)[0].size();
    _corrfunc.resize(N);

    fftw_complex *tmp;
    fftw_plan fft, ifft;

    tmp = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * (N/2+1));

    fft = fftw_plan_dft_r2c_1d(N, &(*data)[0][0], tmp,
                                    FFTW_ESTIMATE);
    ifft = fftw_plan_dft_c2r_1d(N, tmp, &_corrfunc[0],
                                    FFTW_ESTIMATE);
    fftw_execute(fft);

    tmp[0][0] = tmp[0][1] = 0;
    for(int i=1; i<N/2+1; i++) {
        tmp[i][0] = tmp[i][0]*tmp[i][0] + tmp[i][1]*tmp[i][1];
        tmp[i][1] = 0;
    }
    fftw_execute(ifft);

    /*double m=0;
    for(int i=0; i<N; i++) {
        _corrfunc[i] = 0;
        m+=(*data)[0][i];
    }
    m=m/(double)N;
    for(int i=0;i<N; i++)
        for(int j=0; j<N-i-1; j++)
            _corrfunc[i]+=((*data)[0][j]-m)*((*data)[0][(i+j)]-m);
    */
    double d = _corrfunc[0];
    for(int i=0; i<N; i++)
        _corrfunc[i] = _corrfunc[i]/d;
    //cout << *data << endl;
    fftw_destroy_plan(fft);
    fftw_destroy_plan(ifft);
    fftw_free(tmp);
#endif
}

void CrossCorrelate::AutoFourier(vector <double>& ivec){
#ifdef NOFFTW
    throw std::runtime_error("CrossCorrelate::AutoFourier is not compiled-in due to disabling of FFTW - recompile libtool with '--with-ffw'");
#else
    size_t N = ivec.size();
    _corrfunc.resize(N);

    fftw_complex *tmp;
    fftw_plan fft;

    tmp = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * (N/2+1));

    fft = fftw_plan_dft_r2c_1d(N, &ivec[0], tmp, FFTW_ESTIMATE);
    fftw_execute(fft);

    tmp[0][0] = tmp[0][1] = 0;
    for(int i=1; i<N/2+1; i++) {
        tmp[i][0] = tmp[i][0]*tmp[i][0] + tmp[i][1]*tmp[i][1];
        tmp[i][1] = 0;
    }

    // copy the real component of temp to the _corrfunc vector
    for(int i=0; i<N; i++){
        _corrfunc[i] = tmp[i][0];
    }

    fftw_destroy_plan(fft);
    fftw_free(tmp);
#endif
}

void CrossCorrelate::FFTOnly(vector <double>& ivec){
#ifdef NOFFTW
    throw std::runtime_error("CrossCorrelate::FFTOnly is not compiled-in due to disabling of FFTW - recompile libtool with '--with-ffw'");
#else
    size_t N = ivec.size();
    _corrfunc.resize(N);

    fftw_complex *tmp;
    fftw_plan fft;

    tmp = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * (N/2+1));

    fft = fftw_plan_dft_r2c_1d(N, &ivec[0], tmp, FFTW_ESTIMATE);
    fftw_execute(fft);

    // copy the real component of temp to the _corrfunc vector
    for(int i=0; i<N/2+1; i++){
        _corrfunc[i] = tmp[i][0];
    }

    fftw_destroy_plan(fft);
    fftw_free(tmp);
#endif
}

void CrossCorrelate::DCTOnly(vector <double>& ivec){
#ifdef NOFFTW
    throw std::runtime_error("CrossCorrelate::DCTOnly is not compiled-in due to disabling of FFTW - recompile libtool with '--with-ffw'");
#else
    size_t N = ivec.size();
    _corrfunc.resize(N);

    vector <double> tmp;
    tmp.resize(N);
    fftw_plan fft;

    // do real to real discrete cosine trafo
    fft = fftw_plan_r2r_1d(N, &ivec[0], &tmp[0], FFTW_REDFT10, FFTW_ESTIMATE);
    fftw_execute(fft);

    // store results
    for(int i=0; i<N; i++){
        _corrfunc[i] = tmp[i];
    }

    fftw_destroy_plan(fft);
#endif
}

void CrossCorrelate::AutoCosine(vector <double>& ivec){
#ifdef NOFFTW
    throw std::runtime_error("CrossCorrelate::AutoCosing is not compiled-in due to disabling of FFTW - recompile libtool with '--with-ffw'");
#else
    size_t N = ivec.size();
    _corrfunc.resize(N);

    vector <double> tmp;
    tmp.resize(N);
    fftw_plan fft;

    // do real to real discrete cosine trafo
    fft = fftw_plan_r2r_1d(N, &ivec[0], &tmp[0], FFTW_REDFT10, FFTW_ESTIMATE);
    fftw_execute(fft);

    // compute autocorrelation
    tmp[0] = 0;
    for(int i=1; i<N; i++) {
        tmp[i] = tmp[i]*tmp[i];
    }

    // store results
    for(int i=0; i<N; i++){
        _corrfunc[i] = tmp[i];
    }

    fftw_destroy_plan(fft);
#endif
}

void CrossCorrelate::AutoCorr(vector <double>& ivec){
#ifdef NOFFTW
    throw std::runtime_error("CrossCorrelate::AutoCorr is not compiled-in due to disabling of FFTW - recompile libtool with '--with-ffw'");
#else
    size_t N = ivec.size();
    _corrfunc.resize(N);

    fftw_complex *tmp;
    fftw_plan fft, ifft;

    tmp = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * (N/2+1));

    fft = fftw_plan_dft_r2c_1d(N, &ivec[0], tmp, FFTW_ESTIMATE);
    ifft = fftw_plan_dft_c2r_1d(N, tmp, &_corrfunc[0], FFTW_ESTIMATE);
    fftw_execute(fft);

    tmp[0][0] = tmp[0][1] = 0;
    for(int i=1; i<N/2+1; i++) {
        tmp[i][0] = tmp[i][0]*tmp[i][0] + tmp[i][1]*tmp[i][1];
        tmp[i][1] = 0;
    }

    fftw_execute(ifft);

    double d = _corrfunc[0];
    for(int i=0; i<N; i++)
        _corrfunc[i] = _corrfunc[i]/d;

    fftw_destroy_plan(fft);
    fftw_destroy_plan(ifft);
    fftw_free(tmp);
#endif
}

}}
<commit_msg>crosscorrelate.cc: put include <fftw3.h> in ifdef<commit_after>/*
 * Copyright 2009 The VOTCA Development Team (http://www.votca.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include "crosscorrelate.h"

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#ifndef NOFFTW
#include <fftw3.h>
#endif

namespace votca { namespace tools {

/**
    \todo clean implementation!!!
*/
void CrossCorrelate::AutoCorrelate(DataCollection<double>::selection *data, bool average)
{
#ifdef NOFFTW
    throw std::runtime_error("CrossCorrelate::AutoCorrelate is not compiled-in due to disabling of FFTW - recompile libtools with '--with-ffw'");
#else
    size_t N = (*data)[0].size();
    _corrfunc.resize(N);

    fftw_complex *tmp;
    fftw_plan fft, ifft;

    tmp = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * (N/2+1));

    fft = fftw_plan_dft_r2c_1d(N, &(*data)[0][0], tmp,
                                    FFTW_ESTIMATE);
    ifft = fftw_plan_dft_c2r_1d(N, tmp, &_corrfunc[0],
                                    FFTW_ESTIMATE);
    fftw_execute(fft);

    tmp[0][0] = tmp[0][1] = 0;
    for(int i=1; i<N/2+1; i++) {
        tmp[i][0] = tmp[i][0]*tmp[i][0] + tmp[i][1]*tmp[i][1];
        tmp[i][1] = 0;
    }
    fftw_execute(ifft);

    /*double m=0;
    for(int i=0; i<N; i++) {
        _corrfunc[i] = 0;
        m+=(*data)[0][i];
    }
    m=m/(double)N;
    for(int i=0;i<N; i++)
        for(int j=0; j<N-i-1; j++)
            _corrfunc[i]+=((*data)[0][j]-m)*((*data)[0][(i+j)]-m);
    */
    double d = _corrfunc[0];
    for(int i=0; i<N; i++)
        _corrfunc[i] = _corrfunc[i]/d;
    //cout << *data << endl;
    fftw_destroy_plan(fft);
    fftw_destroy_plan(ifft);
    fftw_free(tmp);
#endif
}

void CrossCorrelate::AutoFourier(vector <double>& ivec){
#ifdef NOFFTW
    throw std::runtime_error("CrossCorrelate::AutoFourier is not compiled-in due to disabling of FFTW - recompile libtools with '--with-ffw'");
#else
    size_t N = ivec.size();
    _corrfunc.resize(N);

    fftw_complex *tmp;
    fftw_plan fft;

    tmp = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * (N/2+1));

    fft = fftw_plan_dft_r2c_1d(N, &ivec[0], tmp, FFTW_ESTIMATE);
    fftw_execute(fft);

    tmp[0][0] = tmp[0][1] = 0;
    for(int i=1; i<N/2+1; i++) {
        tmp[i][0] = tmp[i][0]*tmp[i][0] + tmp[i][1]*tmp[i][1];
        tmp[i][1] = 0;
    }

    // copy the real component of temp to the _corrfunc vector
    for(int i=0; i<N; i++){
        _corrfunc[i] = tmp[i][0];
    }

    fftw_destroy_plan(fft);
    fftw_free(tmp);
#endif
}

void CrossCorrelate::FFTOnly(vector <double>& ivec){
#ifdef NOFFTW
    throw std::runtime_error("CrossCorrelate::FFTOnly is not compiled-in due to disabling of FFTW - recompile libtools with '--with-ffw'");
#else
    size_t N = ivec.size();
    _corrfunc.resize(N);

    fftw_complex *tmp;
    fftw_plan fft;

    tmp = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * (N/2+1));

    fft = fftw_plan_dft_r2c_1d(N, &ivec[0], tmp, FFTW_ESTIMATE);
    fftw_execute(fft);

    // copy the real component of temp to the _corrfunc vector
    for(int i=0; i<N/2+1; i++){
        _corrfunc[i] = tmp[i][0];
    }

    fftw_destroy_plan(fft);
    fftw_free(tmp);
#endif
}

void CrossCorrelate::DCTOnly(vector <double>& ivec){
#ifdef NOFFTW
    throw std::runtime_error("CrossCorrelate::DCTOnly is not compiled-in due to disabling of FFTW - recompile libtools with '--with-ffw'");
#else
    size_t N = ivec.size();
    _corrfunc.resize(N);

    vector <double> tmp;
    tmp.resize(N);
    fftw_plan fft;

    // do real to real discrete cosine trafo
    fft = fftw_plan_r2r_1d(N, &ivec[0], &tmp[0], FFTW_REDFT10, FFTW_ESTIMATE);
    fftw_execute(fft);

    // store results
    for(int i=0; i<N; i++){
        _corrfunc[i] = tmp[i];
    }

    fftw_destroy_plan(fft);
#endif
}

void CrossCorrelate::AutoCosine(vector <double>& ivec){
#ifdef NOFFTW
    throw std::runtime_error("CrossCorrelate::AutoCosing is not compiled-in due to disabling of FFTW - recompile libtools with '--with-ffw'");
#else
    size_t N = ivec.size();
    _corrfunc.resize(N);

    vector <double> tmp;
    tmp.resize(N);
    fftw_plan fft;

    // do real to real discrete cosine trafo
    fft = fftw_plan_r2r_1d(N, &ivec[0], &tmp[0], FFTW_REDFT10, FFTW_ESTIMATE);
    fftw_execute(fft);

    // compute autocorrelation
    tmp[0] = 0;
    for(int i=1; i<N; i++) {
        tmp[i] = tmp[i]*tmp[i];
    }

    // store results
    for(int i=0; i<N; i++){
        _corrfunc[i] = tmp[i];
    }

    fftw_destroy_plan(fft);
#endif
}

void CrossCorrelate::AutoCorr(vector <double>& ivec){
#ifdef NOFFTW
    throw std::runtime_error("CrossCorrelate::AutoCorr is not compiled-in due to disabling of FFTW - recompile libtool with '--with-ffw'");
#else
    size_t N = ivec.size();
    _corrfunc.resize(N);

    fftw_complex *tmp;
    fftw_plan fft, ifft;

    tmp = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * (N/2+1));

    fft = fftw_plan_dft_r2c_1d(N, &ivec[0], tmp, FFTW_ESTIMATE);
    ifft = fftw_plan_dft_c2r_1d(N, tmp, &_corrfunc[0], FFTW_ESTIMATE);
    fftw_execute(fft);

    tmp[0][0] = tmp[0][1] = 0;
    for(int i=1; i<N/2+1; i++) {
        tmp[i][0] = tmp[i][0]*tmp[i][0] + tmp[i][1]*tmp[i][1];
        tmp[i][1] = 0;
    }

    fftw_execute(ifft);

    double d = _corrfunc[0];
    for(int i=0; i<N; i++)
        _corrfunc[i] = _corrfunc[i]/d;

    fftw_destroy_plan(fft);
    fftw_destroy_plan(ifft);
    fftw_free(tmp);
#endif
}

}}
<|endoftext|>


<commit_before>#include <tensorflow/core/common_runtime/constant_folding.h>
#include <tensorflow/core/graph/graph_constructor.h>
#include <tensorflow/core/graph/node_builder.h>
#include <tensorflow/core/graph/subgraph.h>
#include <tensorflow/core/platform/init_main.h>
#include <tensorflow/core/public/session.h>
#include <tensorflow/core/util/command_line_flags.h>
#include <tensorflow/tools/graph_transforms/transform_utils.h>

namespace tensorflow {
namespace graph_transforms {

// Remove control depdencies in preparation for inference.
// In the tensorflow graph, control dependencies are represented as extra
// inputs which are referenced with "^tensor_name".
// See node_def.proto for more details.
Status RemoveControlDependencies(const GraphDef& input_graph_def,
                const TransformFuncContext& context,
                GraphDef* output_graph_def) {
    output_graph_def->Clear();
    for (const NodeDef& node : input_graph_def.node()) {
        NodeDef* new_node = output_graph_def->mutable_node()->Add();
        *new_node = node;
        new_node->clear_input();
        for (const auto& input : node.input()) {
            if (input[0] != '^') {
                new_node->add_input(input);
            }
        }
    }
    return Status::OK();
}

REGISTER_GRAPH_TRANSFORM("remove_control_dependencies", RemoveControlDependencies);

}  // namespace graph_transforms
}  // namespace tensorflow
<commit_msg>remove unnecessary includes<commit_after>#include <tensorflow/core/graph/graph_constructor.h>
#include <tensorflow/core/graph/node_builder.h>
#include <tensorflow/tools/graph_transforms/transform_utils.h>

namespace tensorflow {
namespace graph_transforms {

// Remove control depdencies in preparation for inference.
// In the tensorflow graph, control dependencies are represented as extra
// inputs which are referenced with "^tensor_name".
// See node_def.proto for more details.
Status RemoveControlDependencies(const GraphDef& input_graph_def,
                const TransformFuncContext& context,
                GraphDef* output_graph_def) {
    output_graph_def->Clear();
    for (const NodeDef& node : input_graph_def.node()) {
        NodeDef* new_node = output_graph_def->mutable_node()->Add();
        *new_node = node;
        new_node->clear_input();
        for (const auto& input : node.input()) {
            if (input[0] != '^') {
                new_node->add_input(input);
            }
        }
    }
    return Status::OK();
}

REGISTER_GRAPH_TRANSFORM("remove_control_dependencies", RemoveControlDependencies);

}  // namespace graph_transforms
}  // namespace tensorflow
<|endoftext|>


<commit_before>#include "breakpoint.h"
#include <windows.h>
#include <tlhelp32.h>
#include <algorithm>
#include <iostream>

const char HWBreakpoint::m_originalOpcode[8] = { 0x48, 0x83, 0xEC, 0x48, 0x4C, 0x8B, 0xC9, 0x48 };
HWBreakpoint::HWBreakpoint()
{
	ZeroMemory(m_address, sizeof(m_address));
	m_countActive = 0;

	BuildTrampoline();

	m_workerSignal = CreateEvent(NULL, FALSE, FALSE, NULL);
	m_workerDone = CreateEvent(NULL, FALSE, FALSE, NULL);
	m_workerThread = CreateThread(NULL, 0, WorkerThreadProc, this, 0, NULL);
	WaitForSingleObject(m_workerDone, INFINITE);
}

HWBreakpoint::~HWBreakpoint()
{
	CriticalSection::Scope lock(m_cs);
	{
		ZeroMemory(m_address, sizeof(m_address));
		SetForThreads();
	}

	m_pendingThread.tid = -1;
	SetEvent(m_workerSignal);
	WaitForSingleObject(m_workerThread, INFINITE);
	CloseHandle(m_workerDone);
	CloseHandle(m_workerSignal);
	CloseHandle(m_workerThread);
}

bool HWBreakpoint::Set(void* address, int len, Condition when)
{
	HWBreakpoint& bp = GetInstance();
	{
		CriticalSection::Scope lock(bp.m_cs);
		for (int index = 0; index < 4; ++index)
			if (bp.m_address[index] == nullptr)
			{
				bp.m_address[index] = address;
				bp.m_len[index] = len;
				bp.m_when[index] = when;
				if (bp.m_countActive++ == 0)
					bp.ToggleThreadHook(true);
				bp.SetForThreads();
				return true;
			}
	}

	return false;
}

bool HWBreakpoint::Clear(void* address)
{
	HWBreakpoint& bp = GetInstance();
	{
		CriticalSection::Scope lock(bp.m_cs);
		for (int index = 0; index < 4; ++index)
			if (bp.m_address[index] == address)
			{
				bp.m_address[index] = nullptr;
				if (--bp.m_countActive == 0)
					bp.ToggleThreadHook(false);
				bp.SetForThreads();
				return true;
			}
	}

	return false;
}

void HWBreakpoint::ToggleThread(DWORD tid, bool enableBP)
{
	HWBreakpoint& bp = GetInstance();
	{
		CriticalSection::Scope lock(bp.m_cs);
		bp.m_pendingThread.tid = tid;
		bp.m_pendingThread.enable = enableBP;
		SetEvent(bp.m_workerSignal);
		WaitForSingleObject(bp.m_workerDone, INFINITE);
	}
}

void HWBreakpoint::BuildTrampoline()
{
	DWORD64* rtlThreadStartAddress = (DWORD64*)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlUserThreadStart");

	SYSTEM_INFO si;
	GetSystemInfo(&si);

	DWORD64 gMinAddress = (DWORD64)si.lpMinimumApplicationAddress;
	DWORD64 gMaxAddress = (DWORD64)si.lpMaximumApplicationAddress;
	DWORD64 minAddr = std::max<DWORD64>(gMinAddress, (DWORD64)rtlThreadStartAddress - 0x20000000);
	DWORD64 maxAddr = std::min<DWORD64>(gMaxAddress, (DWORD64)rtlThreadStartAddress + 0x20000000);

	const size_t BlockSize = 0x10000;
	intptr_t min = minAddr / BlockSize;
	intptr_t max = maxAddr / BlockSize;
	int rel = 0;
	m_trampoline = nullptr;
	MEMORY_BASIC_INFORMATION mi = { 0 };
	for (int i = 0; i < (max - min + 1); ++i)
	{
		rel = -rel + (i & 1);
		void* pQuery = reinterpret_cast<void*>(((min + max) / 2 + rel) * BlockSize);
		VirtualQuery(pQuery, &mi, sizeof(mi));
		if (mi.State == MEM_FREE)
		{
			m_trampoline = (unsigned char*)VirtualAlloc(pQuery, BlockSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
			if (m_trampoline != nullptr)
				break;
		}
	}

	if (!m_trampoline)
		return;

	*(unsigned char*)	&m_trampoline[0] = 0x51;				// push rcx
	*(unsigned char*)	&m_trampoline[1] = 0x52;				// push rdx
	*(unsigned short*)	&m_trampoline[2] = 0x15FF;				// call
	*(DWORD*)			&m_trampoline[4] = 0x00000017;			//			ThreadDeutor
	*(unsigned char*)	&m_trampoline[8] = 0x5A;				// pop rdx
	*(unsigned char*)	&m_trampoline[9] = 0x59;				// pop rcx

	*(DWORD*)			&m_trampoline[10] = 0x48EC8348;			// sub rsp, 0x48	(2 instruction from prologe of target hook)
	*(unsigned short*)	&m_trampoline[14] = 0x8B4C;				// mov r9,
	*(unsigned char*)	&m_trampoline[16] = 0xC9;				//			rcx
	*(short*)			&m_trampoline[17] = 0x25FF;				// jmp
	*(DWORD*)			&m_trampoline[19] = 0x00000000;

	// address data for call & jump
	*(DWORD64*)			&m_trampoline[23] = (DWORD64)((unsigned char*)rtlThreadStartAddress + 7);
	*(DWORD64*)			&m_trampoline[31] = (DWORD64)ThreadDeutor;
}

void HWBreakpoint::ToggleThreadHook(bool set)
{
	DWORD oldProtect;
	DWORD64* rtlThreadStartAddress = (DWORD64*)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlUserThreadStart");
	if (m_trampoline && set)
	{
		VirtualProtect(rtlThreadStartAddress, 5, PAGE_EXECUTE_READWRITE, &oldProtect);
		unsigned char* b = (unsigned char*)rtlThreadStartAddress;

		// TODO: replace with one atomic operation
		b[0] = 0xE9;
		*(DWORD*)&b[1] = (DWORD)m_trampoline - (DWORD)b - 5;

		VirtualProtect(rtlThreadStartAddress, 5, oldProtect, &oldProtect);
	}
	else if (*rtlThreadStartAddress != *(DWORD64*)m_originalOpcode)
	{
		VirtualProtect(rtlThreadStartAddress, 5, PAGE_EXECUTE_READWRITE, &oldProtect);
		*rtlThreadStartAddress = *(DWORD64*)m_originalOpcode;
		VirtualProtect(rtlThreadStartAddress, 5, oldProtect, &oldProtect);
	}
}

void HWBreakpoint::ThreadDeutor()
{
	HWBreakpoint& bp = GetInstance();
	{
		CriticalSection::Scope lock(bp.m_cs);
		{
			bp.m_pendingThread.tid = GetCurrentThreadId();
			bp.m_pendingThread.enable = true;
			SetEvent(bp.m_workerSignal);
			WaitForSingleObject(bp.m_workerDone, INFINITE);
		}
	}
}

void HWBreakpoint::SetForThreads()
{
	const DWORD pid = GetCurrentProcessId();

	HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
	THREADENTRY32 te32;
	hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
	if (hThreadSnap == INVALID_HANDLE_VALUE)
		return;

	te32.dwSize = sizeof(THREADENTRY32);
	if(!Thread32First(hThreadSnap, &te32))
	{
		CloseHandle(hThreadSnap);
		return;
	}

	do
	{
		if(te32.th32OwnerProcessID == pid)
		{
			CriticalSection::Scope lock(m_cs);
			{
				m_pendingThread.tid = te32.th32ThreadID;
				m_pendingThread.enable = true;
				SetEvent(m_workerSignal);
				WaitForSingleObject(m_workerDone, INFINITE);
			}
		}
	} while(Thread32Next(hThreadSnap, &te32));
}

void HWBreakpoint::SetThread(DWORD tid, bool enableBP)
{
	// this function supposed to be called only from worker thread
	if (GetCurrentThreadId() == tid)
		return;

	HANDLE hThread = OpenThread(THREAD_GET_CONTEXT | THREAD_SET_CONTEXT |  THREAD_SUSPEND_RESUME, FALSE, tid);
	if (!hThread)
		return;

	CONTEXT cxt;
	cxt.ContextFlags = CONTEXT_DEBUG_REGISTERS;

	if (SuspendThread(hThread) == -1)
		goto Final;

	if (!GetThreadContext(hThread, &cxt))
		goto Final;

	for (int index = 0; index < 4; ++index)
	{
		const bool isSet = m_address[index] != nullptr;
		SetBits(cxt.Dr7, index*2, 1, isSet);

		if (isSet)
		{
			switch (index)
			{
			case 0: cxt.Dr0 = (DWORD_PTR) m_address[index]; break;
			case 1: cxt.Dr1 = (DWORD_PTR) m_address[index]; break;
			case 2: cxt.Dr2 = (DWORD_PTR) m_address[index]; break;
			case 3: cxt.Dr3 = (DWORD_PTR) m_address[index]; break;
			}

			SetBits(cxt.Dr7, 16 + (index*4), 2, m_when[index]);
			SetBits(cxt.Dr7, 18 + (index*4), 2, m_len[index]);
		}
	}

	if (!SetThreadContext(hThread, &cxt))
		goto Final;

	if (ResumeThread(hThread) == -1)
		goto Final;

	std::cout << "Set BP for Thread: " << tid << std::endl;

Final:
	CloseHandle(hThread);
}

DWORD HWBreakpoint::WorkerThreadProc(LPVOID lpParameter)
{
	HWBreakpoint& bp = *(HWBreakpoint*)lpParameter;

	SetEvent(bp.m_workerDone);

	while (WaitForSingleObject(bp.m_workerSignal, INFINITE) == WAIT_OBJECT_0)
	{
		// signal for abort
		if (bp.m_pendingThread.tid == -1)
			return 0;

		bp.SetThread(bp.m_pendingThread.tid, bp.m_pendingThread.enable);
		SetEvent(bp.m_workerDone);
	}

	return 0;
}<commit_msg>fix release build<commit_after>#include "breakpoint.h"
#include <windows.h>
#include <tlhelp32.h>
#include <algorithm>
#include <iostream>

const char HWBreakpoint::m_originalOpcode[8] = { 0x48, 0x83, 0xEC, 0x48, 0x4C, 0x8B, 0xC9, 0x48 };
HWBreakpoint::HWBreakpoint()
{
	ZeroMemory(m_address, sizeof(m_address));
	m_countActive = 0;

	BuildTrampoline();

	m_workerSignal = CreateEvent(NULL, FALSE, FALSE, NULL);
	m_workerDone = CreateEvent(NULL, FALSE, FALSE, NULL);
	m_workerThread = CreateThread(NULL, 0, WorkerThreadProc, this, 0, NULL);
	WaitForSingleObject(m_workerDone, INFINITE);
}

HWBreakpoint::~HWBreakpoint()
{
	CriticalSection::Scope lock(m_cs);
	{
		ZeroMemory(m_address, sizeof(m_address));
		SetForThreads();
	}

	m_pendingThread.tid = -1;
	SetEvent(m_workerSignal);
	WaitForSingleObject(m_workerThread, INFINITE);
	CloseHandle(m_workerDone);
	CloseHandle(m_workerSignal);
	CloseHandle(m_workerThread);
}

bool HWBreakpoint::Set(void* address, int len, Condition when)
{
	HWBreakpoint& bp = GetInstance();
	{
		CriticalSection::Scope lock(bp.m_cs);
		for (int index = 0; index < 4; ++index)
			if (bp.m_address[index] == nullptr)
			{
				bp.m_address[index] = address;
				bp.m_len[index] = len;
				bp.m_when[index] = when;
				if (bp.m_countActive++ == 0)
					bp.ToggleThreadHook(true);
				bp.SetForThreads();
				return true;
			}
	}

	return false;
}

bool HWBreakpoint::Clear(void* address)
{
	HWBreakpoint& bp = GetInstance();
	{
		CriticalSection::Scope lock(bp.m_cs);
		for (int index = 0; index < 4; ++index)
			if (bp.m_address[index] == address)
			{
				bp.m_address[index] = nullptr;
				if (--bp.m_countActive == 0)
					bp.ToggleThreadHook(false);
				bp.SetForThreads();
				return true;
			}
	}

	return false;
}

void HWBreakpoint::ToggleThread(DWORD tid, bool enableBP)
{
	HWBreakpoint& bp = GetInstance();
	{
		CriticalSection::Scope lock(bp.m_cs);
		bp.m_pendingThread.tid = tid;
		bp.m_pendingThread.enable = enableBP;
		SetEvent(bp.m_workerSignal);
		WaitForSingleObject(bp.m_workerDone, INFINITE);
	}
}

void HWBreakpoint::BuildTrampoline()
{
	DWORD64* rtlThreadStartAddress = (DWORD64*)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlUserThreadStart");

	SYSTEM_INFO si;
	GetSystemInfo(&si);

	DWORD64 gMinAddress = (DWORD64)si.lpMinimumApplicationAddress;
	DWORD64 gMaxAddress = (DWORD64)si.lpMaximumApplicationAddress;
	DWORD64 minAddr = std::max<DWORD64>(gMinAddress, (DWORD64)rtlThreadStartAddress - 0x20000000);
	DWORD64 maxAddr = std::min<DWORD64>(gMaxAddress, (DWORD64)rtlThreadStartAddress + 0x20000000);

	const size_t BlockSize = 0x10000;
	intptr_t min = minAddr / BlockSize;
	intptr_t max = maxAddr / BlockSize;
	int rel = 0;
	m_trampoline = nullptr;
	MEMORY_BASIC_INFORMATION mi = { 0 };
	for (int i = 0; i < (max - min + 1); ++i)
	{
		rel = -rel + (i & 1);
		void* pQuery = reinterpret_cast<void*>(((min + max) / 2 + rel) * BlockSize);
		VirtualQuery(pQuery, &mi, sizeof(mi));
		if (mi.State == MEM_FREE)
		{
			m_trampoline = (unsigned char*)VirtualAlloc(pQuery, BlockSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
			if (m_trampoline != nullptr)
				break;
		}
	}

	if (!m_trampoline)
		return;

	*(unsigned char*)	&m_trampoline[0] = 0x51;				// push rcx
	*(unsigned char*)	&m_trampoline[1] = 0x52;				// push rdx
	*(unsigned char*)	&m_trampoline[2] = 0x52;				// push rdx
	*(unsigned short*)	&m_trampoline[3] = 0x15FF;				// call
	*(DWORD*)			&m_trampoline[5] = 0x00000018;			//			ThreadDeutor
	*(unsigned char*)	&m_trampoline[9] = 0x5A;				// pop rdx
	*(unsigned char*)	&m_trampoline[10] = 0x5A;				// pop rdx
	*(unsigned char*)	&m_trampoline[11] = 0x59;				// pop rcx

	*(DWORD*)			&m_trampoline[12] = 0x48EC8348;			// sub rsp, 0x48	(2 instruction from prologe of target hook)
	*(unsigned short*)	&m_trampoline[16] = 0x8B4C;				// mov r9,
	*(unsigned char*)	&m_trampoline[18] = 0xC9;				//			rcx
	*(short*)			&m_trampoline[19] = 0x25FF;				// jmp
	*(DWORD*)			&m_trampoline[21] = 0x00000000;			//		rtlThreadStartAddress + 7

	// address data for call & jump
	*(DWORD64*)			&m_trampoline[25] = (DWORD64)((unsigned char*)rtlThreadStartAddress + 7);
	*(DWORD64*)			&m_trampoline[33] = (DWORD64)ThreadDeutor;
}

void HWBreakpoint::ToggleThreadHook(bool set)
{
	DWORD oldProtect;
	DWORD64* rtlThreadStartAddress = (DWORD64*)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlUserThreadStart");
	if (m_trampoline && set)
	{
		VirtualProtect(rtlThreadStartAddress, 5, PAGE_EXECUTE_READWRITE, &oldProtect);
		unsigned char* b = (unsigned char*)rtlThreadStartAddress;

		// TODO: replace with one atomic operation
		b[0] = 0xE9;
		*(DWORD*)&b[1] = (DWORD)m_trampoline - (DWORD)b - 5;

		VirtualProtect(rtlThreadStartAddress, 5, oldProtect, &oldProtect);
	}
	else if (*rtlThreadStartAddress != *(DWORD64*)m_originalOpcode)
	{
		VirtualProtect(rtlThreadStartAddress, 5, PAGE_EXECUTE_READWRITE, &oldProtect);
		*rtlThreadStartAddress = *(DWORD64*)m_originalOpcode;
		VirtualProtect(rtlThreadStartAddress, 5, oldProtect, &oldProtect);
	}
}

void HWBreakpoint::ThreadDeutor()
{
	HWBreakpoint& bp = GetInstance();
	{
		CriticalSection::Scope lock(bp.m_cs);
		{
			bp.m_pendingThread.tid = GetCurrentThreadId();
			bp.m_pendingThread.enable = true;
			SetEvent(bp.m_workerSignal);
			WaitForSingleObject(bp.m_workerDone, INFINITE);
		}
	}
}

void HWBreakpoint::SetForThreads()
{
	const DWORD pid = GetCurrentProcessId();

	HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
	THREADENTRY32 te32;
	hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
	if (hThreadSnap == INVALID_HANDLE_VALUE)
		return;

	te32.dwSize = sizeof(THREADENTRY32);
	if(!Thread32First(hThreadSnap, &te32))
	{
		CloseHandle(hThreadSnap);
		return;
	}

	do
	{
		if(te32.th32OwnerProcessID == pid)
		{
			CriticalSection::Scope lock(m_cs);
			{
				m_pendingThread.tid = te32.th32ThreadID;
				m_pendingThread.enable = true;
				SetEvent(m_workerSignal);
				WaitForSingleObject(m_workerDone, INFINITE);
			}
		}
	} while(Thread32Next(hThreadSnap, &te32));
}

void HWBreakpoint::SetThread(DWORD tid, bool enableBP)
{
	// this function supposed to be called only from worker thread
	if (GetCurrentThreadId() == tid)
		return;

	HANDLE hThread = OpenThread(THREAD_GET_CONTEXT | THREAD_SET_CONTEXT |  THREAD_SUSPEND_RESUME, FALSE, tid);
	if (!hThread)
		return;

	CONTEXT cxt;
	cxt.ContextFlags = CONTEXT_DEBUG_REGISTERS;

	if (SuspendThread(hThread) == -1)
		goto Final;

	if (!GetThreadContext(hThread, &cxt))
		goto Final;

	for (int index = 0; index < 4; ++index)
	{
		const bool isSet = m_address[index] != nullptr;
		SetBits(cxt.Dr7, index*2, 1, isSet);

		if (isSet)
		{
			switch (index)
			{
			case 0: cxt.Dr0 = (DWORD_PTR) m_address[index]; break;
			case 1: cxt.Dr1 = (DWORD_PTR) m_address[index]; break;
			case 2: cxt.Dr2 = (DWORD_PTR) m_address[index]; break;
			case 3: cxt.Dr3 = (DWORD_PTR) m_address[index]; break;
			}

			SetBits(cxt.Dr7, 16 + (index*4), 2, m_when[index]);
			SetBits(cxt.Dr7, 18 + (index*4), 2, m_len[index]);
		}
	}

	if (!SetThreadContext(hThread, &cxt))
		goto Final;

	if (ResumeThread(hThread) == -1)
		goto Final;

	std::cout << "Set BP for Thread: " << tid << std::endl;

Final:
	CloseHandle(hThread);
}

DWORD HWBreakpoint::WorkerThreadProc(LPVOID lpParameter)
{
	HWBreakpoint& bp = *(HWBreakpoint*)lpParameter;

	SetEvent(bp.m_workerDone);

	while (WaitForSingleObject(bp.m_workerSignal, INFINITE) == WAIT_OBJECT_0)
	{
		// signal for abort
		if (bp.m_pendingThread.tid == -1)
			return 0;

		bp.SetThread(bp.m_pendingThread.tid, bp.m_pendingThread.enable);
		SetEvent(bp.m_workerDone);
	}

	return 0;
}<|endoftext|>


<commit_before>// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Copyright (C) 2021 Intel Corporation

#include <algorithm>
#include <sstream>

#include "streaming/onevpl/engine/decode/decode_engine_legacy.hpp"
#include "streaming/onevpl/engine/transcode/transcode_engine_legacy.hpp"
#include "streaming/onevpl/accelerators/accel_policy_dx11.hpp"
#include "streaming/onevpl/accelerators/accel_policy_cpu.hpp"
#include "streaming/onevpl/accelerators/accel_policy_va_api.hpp"
#include "streaming/onevpl/utils.hpp"
#include "streaming/onevpl/cfg_params_parser.hpp"
#include "streaming/onevpl/data_provider_defines.hpp"

#include "streaming/onevpl/source_priv.hpp"
#include "logger.hpp"

#ifndef HAVE_ONEVPL
namespace cv {
namespace gapi {
namespace wip {
namespace onevpl {
bool GSource::Priv::pull(cv::gapi::wip::Data&) {
    return true;
}
GMetaArg GSource::Priv::descr_of() const {
    return {};
}
} // namespace onevpl
} // namespace wip
} // namespace gapi
} // namespace cv

#else // HAVE_ONEVPL

// TODO global variable move it into Source after CloneSession issue resolving
mfxLoader mfx_handle = MFXLoad();
int impl_number = 0;

namespace cv {
namespace gapi {
namespace wip {
namespace onevpl {

enum {
    VPL_NEW_API_MAJOR_VERSION = 2,
    VPL_NEW_API_MINOR_VERSION = 2
};

GSource::Priv::Priv() :
//    mfx_handle(MFXLoad()),
    mfx_impl_description(),
    mfx_handle_configs(),
    cfg_params(),
    mfx_session(),
    description(),
    description_is_valid(false),
    engine(),
    consumed_frames_count()
{
    GAPI_LOG_INFO(nullptr, "Initialized MFX handle: " << mfx_handle);
}

GSource::Priv::Priv(std::shared_ptr<IDataProvider> provider,
                    const std::vector<CfgParam>& params,
                    std::shared_ptr<IDeviceSelector> device_selector) :
     GSource::Priv()
{
    // Enable Config
    if (params.empty())
    {
        GAPI_LOG_INFO(nullptr, "No special cfg params requested - use default");
        this->cfg_params = getDefaultCfgParams();
    }
    else
    {
         this->cfg_params = params;
    }

    GAPI_LOG_DEBUG(nullptr, "Requested cfg params count: " << cfg_params.size());
    this->mfx_handle_configs.resize(cfg_params.size());

    // Build VPL handle config from major input params
    // VPL dispatcher then uses this config handle to look up for all existing VPL impl
    // satisfying major input params and available in the system
    GAPI_LOG_INFO(nullptr, "Creating VPL config from input params");
    auto cfg_param_it = cfg_params.begin();
    for (mfxConfig& cfg_inst : mfx_handle_configs) {
         cfg_inst = MFXCreateConfig(mfx_handle);
         GAPI_Assert(cfg_inst && "MFXCreateConfig failed");

        if (!cfg_param_it->is_major()) {
            GAPI_LOG_DEBUG(nullptr, "Skip not major param: " << cfg_param_it->to_string());
            ++cfg_param_it;
            continue;
        }

        GAPI_LOG_DEBUG(nullptr, "Apply major param: " << cfg_param_it->to_string());
        mfxVariant mfx_param = cfg_param_to_mfx_variant(*cfg_param_it);
        mfxStatus sts = MFXSetConfigFilterProperty(cfg_inst,
                                                   (mfxU8 *)cfg_param_it->get_name().c_str(),
                                                   mfx_param);
        if (sts != MFX_ERR_NONE )
        {
            GAPI_LOG_WARNING(nullptr, "MFXSetConfigFilterProperty failed, error: " <<
                                      mfxstatus_to_string(sts) <<
                                      " - for \"" << cfg_param_it->get_name() << "\"");
            GAPI_Assert(false && "MFXSetConfigFilterProperty failed");
        }

        mfx_param.Type     = MFX_VARIANT_TYPE_U32;
        mfx_param.Data.U32 = MFX_EXTBUFF_VPP_SCALING;
        sts = MFXSetConfigFilterProperty(cfg_inst,
        (mfxU8 *)"mfxImplDescription.mfxVPPDescription.filter.FilterFourCC",
        mfx_param);

        if (sts != MFX_ERR_NONE )
        {
            GAPI_LOG_WARNING(nullptr, "MFXSetConfigFilterProperty failed, error: " <<
                                      mfxstatus_to_string(sts) <<
                                      " - for \"mfxImplDescription.mfxVPPDescription.filter.FilterFourCC\"");
            GAPI_Assert(false && "MFXSetConfigFilterProperty failed");
        }

        ++cfg_param_it;
    }

    // collect optional-preferred input parameters from input params
    // which may (optionally) or may not be used to choose the most preferable
    // VPL implementation (for example, specific API version or Debug/Release VPL build)
    std::vector<CfgParam> preferred_params;
    std::copy_if(cfg_params.begin(), cfg_params.end(), std::back_inserter(preferred_params),
                 [] (const CfgParam& param) { return !param.is_major(); });
    std::sort(preferred_params.begin(), preferred_params.end());

    GAPI_LOG_DEBUG(nullptr, "Find MFX better implementation from handle: " << mfx_handle <<
                            " is satisfying preferable params count: " << preferred_params.size());
    int i = 0;
    mfxImplDescription *idesc = nullptr;
    std::vector<mfxImplDescription*> available_impl_descriptions;
    std::map<size_t/*matches count*/, int /*impl index*/> matches_count;
    while (MFX_ERR_NONE == MFXEnumImplementations(mfx_handle,
                                                  i,
                                                  MFX_IMPLCAPS_IMPLDESCSTRUCTURE,
                                                  reinterpret_cast<mfxHDL *>(&idesc))) {

        available_impl_descriptions.push_back(idesc);

        std::stringstream ss;
        mfxHDL hImplPath = nullptr;
        if (MFX_ERR_NONE == MFXEnumImplementations(mfx_handle, i, MFX_IMPLCAPS_IMPLPATH, &hImplPath)) {
            if (hImplPath) {
                ss << "Implementation path: "  <<  reinterpret_cast<mfxChar *>(hImplPath) << std::endl;
                MFXDispReleaseImplDescription(mfx_handle, hImplPath);
            }
        }
        ss << *idesc << std::endl;

        GAPI_LOG_INFO(nullptr, "Implementation index: " << i << "\n" << ss.str());

        // Only one VPL implementation is required for GSource here.
        // Let's find intersection params from available impl with preferable input params
        // to find best match.
        // An available VPL implementation with max matching count
        std::vector<CfgParam> impl_params = get_params_from_string<CfgParam>(ss.str());
        std::sort(impl_params.begin(), impl_params.end());
        GAPI_LOG_DEBUG(nullptr, "Find implementation cfg params count: " << impl_params.size());

        std::vector<CfgParam> matched_params;
        std::set_intersection(impl_params.begin(), impl_params.end(),
                                  preferred_params.begin(), preferred_params.end(),
                                  std::back_inserter(matched_params));

        if (preferred_params.empty()) {
            // in case of no input preferrance we consider all params are matched
            // for the first available VPL implementation. It will be a chosen one
            matches_count.emplace(impl_params.size(), i++);
            GAPI_LOG_DEBUG(nullptr, "No preferable params, use the first one implementation");
            break;
        } else {
            GAPI_LOG_DEBUG(nullptr, "Equal param intersection count: " << matched_params.size());
            matches_count.emplace(matches_count.size(), i++);
        }
    }

    // Extract the most suitable VPL implementation by max score
    auto max_match_it = matches_count.rbegin();
    if (max_match_it == matches_count.rend()) {
        std::stringstream ss;
        for (const auto &p : cfg_params) {
            ss << p.to_string() << std::endl;
        }
        GAPI_LOG_WARNING(nullptr, "No one suitable MFX implementation is found, requested params:\n" << ss.str());
        throw std::runtime_error("Cannot find any suitable MFX implementation for requested configuration");
    }

    // TODO impl_number is global for now
    impl_number = max_match_it->second;
    GAPI_LOG_INFO(nullptr, "Chosen implementation index: " << impl_number);

    // release unusable impl available_impl_descriptions
    std::swap(mfx_impl_description, available_impl_descriptions[impl_number]);
    for (mfxImplDescription* unusable_impl_descr : available_impl_descriptions) {
        if (unusable_impl_descr) {
            MFXDispReleaseImplDescription(mfx_handle, unusable_impl_descr);
        }
    }
    available_impl_descriptions.clear();

    // create session for implementation
    mfxStatus sts = MFXCreateSession(mfx_handle, impl_number, &mfx_session);
    if (MFX_ERR_NONE != sts) {
        GAPI_LOG_WARNING(nullptr, "Cannot create MFX Session for implementation index:" <<
                                   std::to_string(impl_number) <<
                                   ", error: " << mfxstatus_to_string(sts));
    }

    GAPI_LOG_INFO(nullptr, "Initialized MFX session: " << mfx_session);

    // create session driving engine if required
    if (!engine) {
        std::unique_ptr<VPLAccelerationPolicy> acceleration = initializeHWAccel(device_selector);

        // TODO  Add factory static method in ProcessingEngineBase
        if (mfx_impl_description->ApiVersion.Major >= VPL_NEW_API_MAJOR_VERSION) {
            GAPI_Assert(false &&
                        "GSource mfx_impl_description->ApiVersion.Major >= VPL_NEW_API_MAJOR_VERSION"
                        " - is not implemented");
        } else {
            const auto& transcode_params = VPLLegacyTranscodeEngine::get_vpp_params(preferred_params);
            if (!transcode_params.empty()) {
                engine.reset(new VPLLegacyTranscodeEngine(std::move(acceleration)));
            } else {
                engine.reset(new VPLLegacyDecodeEngine(std::move(acceleration)));
            }
        }
    }

    // create engine session for processing mfx session pipeline
    auto engine_session_ptr = engine->initialize_session(mfx_session, cfg_params,
                                                         provider);

    const mfxFrameInfo& video_param = engine_session_ptr->get_video_param();

    // set valid description
    description.size = cv::Size {
                            video_param.Width,
                            video_param.Height};
    switch(video_param.FourCC) {
        case MFX_FOURCC_I420:
            throw std::runtime_error("Cannot parse GMetaArg description: MediaFrame doesn't support I420 type");
        case MFX_FOURCC_NV12:
            description.fmt = cv::MediaFormat::NV12;
            break;
        default:
            throw std::runtime_error("Cannot parse GMetaArg description: MediaFrame unknown 'fmt' type: " +
                                     std::to_string(video_param.FourCC));
    }
    description_is_valid = true;

    //prepare session for processing
    engine->process(mfx_session);
}

GSource::Priv::~Priv() {
    engine.reset();

    GAPI_LOG_INFO(nullptr, "consumed frames count: " << consumed_frames_count);
    GAPI_LOG_INFO(nullptr, "Unload MFX implementation description: " << mfx_impl_description);
    MFXDispReleaseImplDescription(mfx_handle, mfx_impl_description);
    GAPI_LOG_INFO(nullptr, "Unload MFX handle: " << mfx_handle);
    //MFXUnload(mfx_handle);
}

std::unique_ptr<VPLAccelerationPolicy> GSource::Priv::initializeHWAccel(std::shared_ptr<IDeviceSelector> selector)
{
    std::unique_ptr<VPLAccelerationPolicy> ret;

    auto accel_mode_it = std::find_if(cfg_params.begin(), cfg_params.end(), [] (const CfgParam& value) {
        return value.get_name() ==  CfgParam::acceleration_mode_name();
    });
    if (accel_mode_it == cfg_params.end())
    {
        GAPI_LOG_DEBUG(nullptr, "No HW Accel requested. Use CPU");

        ret.reset(new VPLCPUAccelerationPolicy(selector));
        return ret;
    }

    GAPI_LOG_DEBUG(nullptr, "Add HW acceleration support");
    mfxVariant accel_mode = cfg_param_to_mfx_variant(*accel_mode_it);

    switch(accel_mode.Data.U32) {
        case MFX_ACCEL_MODE_VIA_D3D11:
        {
            std::unique_ptr<VPLDX11AccelerationPolicy> cand(new VPLDX11AccelerationPolicy(selector));
            ret = std::move(cand);
            break;
        }
        case MFX_ACCEL_MODE_VIA_VAAPI:
        {
            std::unique_ptr<VPLVAAPIAccelerationPolicy> cand(new VPLVAAPIAccelerationPolicy(selector));
            ret = std::move(cand);
            break;
        }
        case MFX_ACCEL_MODE_NA:
        {
            std::unique_ptr<VPLCPUAccelerationPolicy> cand(new VPLCPUAccelerationPolicy(selector));
            ret = std::move(cand);
            break;
        }
        default:
        {
            GAPI_LOG_WARNING(nullptr, "Cannot initialize HW Accel: "
                                      "invalid accelerator type: " <<
                                      std::to_string(accel_mode.Data.U32));
            GAPI_Assert(false && "Cannot initialize HW Accel");
        }
    }

    return ret;
}

const std::vector<CfgParam>& GSource::Priv::getDefaultCfgParams()
{
#ifdef __WIN32__
    static const std::vector<CfgParam> def_params =
        get_params_from_string<CfgParam>(
                    "mfxImplDescription.Impl: MFX_IMPL_TYPE_HARDWARE\n"
                    "mfxImplDescription.AccelerationMode: MFX_ACCEL_MODE_VIA_D3D11\n");
#else
    static const std::vector<CfgParam> def_params =
        get_params_from_string<CfgParam>(
                    "mfxImplDescription.Impl: MFX_IMPL_TYPE_HARDWARE\n");
#endif
    return def_params;
}

const std::vector<CfgParam>& GSource::Priv::getCfgParams() const
{
    return cfg_params;
}

bool GSource::Priv::pull(cv::gapi::wip::Data& data)
{
    ProcessingEngineBase::ExecutionStatus status = ProcessingEngineBase::ExecutionStatus::Continue;
    while (0 == engine->get_ready_frames_count() &&
           status == ProcessingEngineBase::ExecutionStatus::Continue) {
        status = engine->process(mfx_session);
    }

    if (engine->get_ready_frames_count()) {
        engine->get_frame(data);
        consumed_frames_count++;
        return true;
    } else {
        return false;
    }
}

GMetaArg GSource::Priv::descr_of() const
{
    GAPI_Assert(description_is_valid);
    GMetaArg arg(description);
    return arg;
}
} // namespace onevpl
} // namespace wip
} // namespace gapi
} // namespace cv

#endif // HAVE_ONEVPL
<commit_msg>Replace MFX major version assertion to warning<commit_after>// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Copyright (C) 2021 Intel Corporation

#include <algorithm>
#include <sstream>

#include "streaming/onevpl/engine/decode/decode_engine_legacy.hpp"
#include "streaming/onevpl/engine/transcode/transcode_engine_legacy.hpp"
#include "streaming/onevpl/accelerators/accel_policy_dx11.hpp"
#include "streaming/onevpl/accelerators/accel_policy_cpu.hpp"
#include "streaming/onevpl/accelerators/accel_policy_va_api.hpp"
#include "streaming/onevpl/utils.hpp"
#include "streaming/onevpl/cfg_params_parser.hpp"
#include "streaming/onevpl/data_provider_defines.hpp"

#include "streaming/onevpl/source_priv.hpp"
#include "logger.hpp"

#ifndef HAVE_ONEVPL
namespace cv {
namespace gapi {
namespace wip {
namespace onevpl {
bool GSource::Priv::pull(cv::gapi::wip::Data&) {
    return true;
}
GMetaArg GSource::Priv::descr_of() const {
    return {};
}
} // namespace onevpl
} // namespace wip
} // namespace gapi
} // namespace cv

#else // HAVE_ONEVPL

// TODO global variable move it into Source after CloneSession issue resolving
mfxLoader mfx_handle = MFXLoad();
int impl_number = 0;

namespace cv {
namespace gapi {
namespace wip {
namespace onevpl {

enum {
    VPL_NEW_API_MAJOR_VERSION = 2,
    VPL_NEW_API_MINOR_VERSION = 2
};

GSource::Priv::Priv() :
//    mfx_handle(MFXLoad()),
    mfx_impl_description(),
    mfx_handle_configs(),
    cfg_params(),
    mfx_session(),
    description(),
    description_is_valid(false),
    engine(),
    consumed_frames_count()
{
    GAPI_LOG_INFO(nullptr, "Initialized MFX handle: " << mfx_handle);
}

GSource::Priv::Priv(std::shared_ptr<IDataProvider> provider,
                    const std::vector<CfgParam>& params,
                    std::shared_ptr<IDeviceSelector> device_selector) :
     GSource::Priv()
{
    // Enable Config
    if (params.empty())
    {
        GAPI_LOG_INFO(nullptr, "No special cfg params requested - use default");
        this->cfg_params = getDefaultCfgParams();
    }
    else
    {
         this->cfg_params = params;
    }

    GAPI_LOG_DEBUG(nullptr, "Requested cfg params count: " << cfg_params.size());
    this->mfx_handle_configs.resize(cfg_params.size());

    // Build VPL handle config from major input params
    // VPL dispatcher then uses this config handle to look up for all existing VPL impl
    // satisfying major input params and available in the system
    GAPI_LOG_INFO(nullptr, "Creating VPL config from input params");
    auto cfg_param_it = cfg_params.begin();
    for (mfxConfig& cfg_inst : mfx_handle_configs) {
         cfg_inst = MFXCreateConfig(mfx_handle);
         GAPI_Assert(cfg_inst && "MFXCreateConfig failed");

        if (!cfg_param_it->is_major()) {
            GAPI_LOG_DEBUG(nullptr, "Skip not major param: " << cfg_param_it->to_string());
            ++cfg_param_it;
            continue;
        }

        GAPI_LOG_DEBUG(nullptr, "Apply major param: " << cfg_param_it->to_string());
        mfxVariant mfx_param = cfg_param_to_mfx_variant(*cfg_param_it);
        mfxStatus sts = MFXSetConfigFilterProperty(cfg_inst,
                                                   (mfxU8 *)cfg_param_it->get_name().c_str(),
                                                   mfx_param);
        if (sts != MFX_ERR_NONE )
        {
            GAPI_LOG_WARNING(nullptr, "MFXSetConfigFilterProperty failed, error: " <<
                                      mfxstatus_to_string(sts) <<
                                      " - for \"" << cfg_param_it->get_name() << "\"");
            GAPI_Assert(false && "MFXSetConfigFilterProperty failed");
        }

        mfx_param.Type     = MFX_VARIANT_TYPE_U32;
        mfx_param.Data.U32 = MFX_EXTBUFF_VPP_SCALING;
        sts = MFXSetConfigFilterProperty(cfg_inst,
        (mfxU8 *)"mfxImplDescription.mfxVPPDescription.filter.FilterFourCC",
        mfx_param);

        if (sts != MFX_ERR_NONE )
        {
            GAPI_LOG_WARNING(nullptr, "MFXSetConfigFilterProperty failed, error: " <<
                                      mfxstatus_to_string(sts) <<
                                      " - for \"mfxImplDescription.mfxVPPDescription.filter.FilterFourCC\"");
            GAPI_Assert(false && "MFXSetConfigFilterProperty failed");
        }

        ++cfg_param_it;
    }

    // collect optional-preferred input parameters from input params
    // which may (optionally) or may not be used to choose the most preferable
    // VPL implementation (for example, specific API version or Debug/Release VPL build)
    std::vector<CfgParam> preferred_params;
    std::copy_if(cfg_params.begin(), cfg_params.end(), std::back_inserter(preferred_params),
                 [] (const CfgParam& param) { return !param.is_major(); });
    std::sort(preferred_params.begin(), preferred_params.end());

    GAPI_LOG_DEBUG(nullptr, "Find MFX better implementation from handle: " << mfx_handle <<
                            " is satisfying preferable params count: " << preferred_params.size());
    int i = 0;
    mfxImplDescription *idesc = nullptr;
    std::vector<mfxImplDescription*> available_impl_descriptions;
    std::map<size_t/*matches count*/, int /*impl index*/> matches_count;
    while (MFX_ERR_NONE == MFXEnumImplementations(mfx_handle,
                                                  i,
                                                  MFX_IMPLCAPS_IMPLDESCSTRUCTURE,
                                                  reinterpret_cast<mfxHDL *>(&idesc))) {

        available_impl_descriptions.push_back(idesc);

        std::stringstream ss;
        mfxHDL hImplPath = nullptr;
        if (MFX_ERR_NONE == MFXEnumImplementations(mfx_handle, i, MFX_IMPLCAPS_IMPLPATH, &hImplPath)) {
            if (hImplPath) {
                ss << "Implementation path: "  <<  reinterpret_cast<mfxChar *>(hImplPath) << std::endl;
                MFXDispReleaseImplDescription(mfx_handle, hImplPath);
            }
        }
        ss << *idesc << std::endl;

        GAPI_LOG_INFO(nullptr, "Implementation index: " << i << "\n" << ss.str());

        // Only one VPL implementation is required for GSource here.
        // Let's find intersection params from available impl with preferable input params
        // to find best match.
        // An available VPL implementation with max matching count
        std::vector<CfgParam> impl_params = get_params_from_string<CfgParam>(ss.str());
        std::sort(impl_params.begin(), impl_params.end());
        GAPI_LOG_DEBUG(nullptr, "Find implementation cfg params count: " << impl_params.size());

        std::vector<CfgParam> matched_params;
        std::set_intersection(impl_params.begin(), impl_params.end(),
                                  preferred_params.begin(), preferred_params.end(),
                                  std::back_inserter(matched_params));

        if (preferred_params.empty()) {
            // in case of no input preferrance we consider all params are matched
            // for the first available VPL implementation. It will be a chosen one
            matches_count.emplace(impl_params.size(), i++);
            GAPI_LOG_DEBUG(nullptr, "No preferable params, use the first one implementation");
            break;
        } else {
            GAPI_LOG_DEBUG(nullptr, "Equal param intersection count: " << matched_params.size());
            matches_count.emplace(matches_count.size(), i++);
        }
    }

    // Extract the most suitable VPL implementation by max score
    auto max_match_it = matches_count.rbegin();
    if (max_match_it == matches_count.rend()) {
        std::stringstream ss;
        for (const auto &p : cfg_params) {
            ss << p.to_string() << std::endl;
        }
        GAPI_LOG_WARNING(nullptr, "No one suitable MFX implementation is found, requested params:\n" << ss.str());
        throw std::runtime_error("Cannot find any suitable MFX implementation for requested configuration");
    }

    // TODO impl_number is global for now
    impl_number = max_match_it->second;
    GAPI_LOG_INFO(nullptr, "Chosen implementation index: " << impl_number);

    // release unusable impl available_impl_descriptions
    std::swap(mfx_impl_description, available_impl_descriptions[impl_number]);
    for (mfxImplDescription* unusable_impl_descr : available_impl_descriptions) {
        if (unusable_impl_descr) {
            MFXDispReleaseImplDescription(mfx_handle, unusable_impl_descr);
        }
    }
    available_impl_descriptions.clear();

    // create session for implementation
    mfxStatus sts = MFXCreateSession(mfx_handle, impl_number, &mfx_session);
    if (MFX_ERR_NONE != sts) {
        GAPI_LOG_WARNING(nullptr, "Cannot create MFX Session for implementation index:" <<
                                   std::to_string(impl_number) <<
                                   ", error: " << mfxstatus_to_string(sts));
    }

    GAPI_LOG_INFO(nullptr, "Initialized MFX session: " << mfx_session);

    // create session driving engine if required
    if (!engine) {
        std::unique_ptr<VPLAccelerationPolicy> acceleration = initializeHWAccel(device_selector);

        // TODO  Add factory static method in ProcessingEngineBase
        if (mfx_impl_description->ApiVersion.Major >= VPL_NEW_API_MAJOR_VERSION) {
            GAPI_LOG_WARNING(NULL,
                        "GSource mfx_impl_description->ApiVersion.Major >= VPL_NEW_API_MAJOR_VERSION"
                        " - is not implemented. G-API only supports an older version of OneVPL API.");
        }
        const auto& transcode_params = VPLLegacyTranscodeEngine::get_vpp_params(preferred_params);
        if (!transcode_params.empty()) {
            engine.reset(new VPLLegacyTranscodeEngine(std::move(acceleration)));
        } else {
            engine.reset(new VPLLegacyDecodeEngine(std::move(acceleration)));
        }
    }

    // create engine session for processing mfx session pipeline
    auto engine_session_ptr = engine->initialize_session(mfx_session, cfg_params,
                                                         provider);

    const mfxFrameInfo& video_param = engine_session_ptr->get_video_param();

    // set valid description
    description.size = cv::Size {
                            video_param.Width,
                            video_param.Height};
    switch(video_param.FourCC) {
        case MFX_FOURCC_I420:
            throw std::runtime_error("Cannot parse GMetaArg description: MediaFrame doesn't support I420 type");
        case MFX_FOURCC_NV12:
            description.fmt = cv::MediaFormat::NV12;
            break;
        default:
            throw std::runtime_error("Cannot parse GMetaArg description: MediaFrame unknown 'fmt' type: " +
                                     std::to_string(video_param.FourCC));
    }
    description_is_valid = true;

    //prepare session for processing
    engine->process(mfx_session);
}

GSource::Priv::~Priv() {
    engine.reset();

    GAPI_LOG_INFO(nullptr, "consumed frames count: " << consumed_frames_count);
    GAPI_LOG_INFO(nullptr, "Unload MFX implementation description: " << mfx_impl_description);
    MFXDispReleaseImplDescription(mfx_handle, mfx_impl_description);
    GAPI_LOG_INFO(nullptr, "Unload MFX handle: " << mfx_handle);
    //MFXUnload(mfx_handle);
}

std::unique_ptr<VPLAccelerationPolicy> GSource::Priv::initializeHWAccel(std::shared_ptr<IDeviceSelector> selector)
{
    std::unique_ptr<VPLAccelerationPolicy> ret;

    auto accel_mode_it = std::find_if(cfg_params.begin(), cfg_params.end(), [] (const CfgParam& value) {
        return value.get_name() ==  CfgParam::acceleration_mode_name();
    });
    if (accel_mode_it == cfg_params.end())
    {
        GAPI_LOG_DEBUG(nullptr, "No HW Accel requested. Use CPU");

        ret.reset(new VPLCPUAccelerationPolicy(selector));
        return ret;
    }

    GAPI_LOG_DEBUG(nullptr, "Add HW acceleration support");
    mfxVariant accel_mode = cfg_param_to_mfx_variant(*accel_mode_it);

    switch(accel_mode.Data.U32) {
        case MFX_ACCEL_MODE_VIA_D3D11:
        {
            std::unique_ptr<VPLDX11AccelerationPolicy> cand(new VPLDX11AccelerationPolicy(selector));
            ret = std::move(cand);
            break;
        }
        case MFX_ACCEL_MODE_VIA_VAAPI:
        {
            std::unique_ptr<VPLVAAPIAccelerationPolicy> cand(new VPLVAAPIAccelerationPolicy(selector));
            ret = std::move(cand);
            break;
        }
        case MFX_ACCEL_MODE_NA:
        {
            std::unique_ptr<VPLCPUAccelerationPolicy> cand(new VPLCPUAccelerationPolicy(selector));
            ret = std::move(cand);
            break;
        }
        default:
        {
            GAPI_LOG_WARNING(nullptr, "Cannot initialize HW Accel: "
                                      "invalid accelerator type: " <<
                                      std::to_string(accel_mode.Data.U32));
            GAPI_Assert(false && "Cannot initialize HW Accel");
        }
    }

    return ret;
}

const std::vector<CfgParam>& GSource::Priv::getDefaultCfgParams()
{
#ifdef __WIN32__
    static const std::vector<CfgParam> def_params =
        get_params_from_string<CfgParam>(
                    "mfxImplDescription.Impl: MFX_IMPL_TYPE_HARDWARE\n"
                    "mfxImplDescription.AccelerationMode: MFX_ACCEL_MODE_VIA_D3D11\n");
#else
    static const std::vector<CfgParam> def_params =
        get_params_from_string<CfgParam>(
                    "mfxImplDescription.Impl: MFX_IMPL_TYPE_HARDWARE\n");
#endif
    return def_params;
}

const std::vector<CfgParam>& GSource::Priv::getCfgParams() const
{
    return cfg_params;
}

bool GSource::Priv::pull(cv::gapi::wip::Data& data)
{
    ProcessingEngineBase::ExecutionStatus status = ProcessingEngineBase::ExecutionStatus::Continue;
    while (0 == engine->get_ready_frames_count() &&
           status == ProcessingEngineBase::ExecutionStatus::Continue) {
        status = engine->process(mfx_session);
    }

    if (engine->get_ready_frames_count()) {
        engine->get_frame(data);
        consumed_frames_count++;
        return true;
    } else {
        return false;
    }
}

GMetaArg GSource::Priv::descr_of() const
{
    GAPI_Assert(description_is_valid);
    GMetaArg arg(description);
    return arg;
}
} // namespace onevpl
} // namespace wip
} // namespace gapi
} // namespace cv

#endif // HAVE_ONEVPL
<|endoftext|>