<commit_before>
#include "viewer.h"

nanogui::Screen *screen = nullptr;
Control control;
Loader loader;

float width = 800;
float height = 800;

bool mouseDown = false;
bool orthographic = false;
bool wireframe = false;
float cameraViewAngle = 45.0;
float cameraNear = 1.0;
float cameraFar = 100.0;
float lineWidth = 0.5f;
float cameraZoom = 3.0f;
float modelZoom = 3.0f;

Eigen::Matrix4f viewMatrix = Eigen::Matrix4f::Identity();
Eigen::Matrix4f projMatrix = Eigen::Matrix4f::Identity();
Eigen::Matrix4f modelMatrix = Eigen::Matrix4f::Identity();
Eigen::Quaternionf arcballQuat = Eigen::Quaternionf::Identity();

Eigen::Vector3f center(0, 1, 0);
Eigen::Vector4f lineColor(1.0f, 1.0f, 1.0f, 1.0f);
Eigen::Vector3f cameraEye(0, 0, 5);
Eigen::Vector3f cameraCenter(0, 1, 0);
Eigen::Vector3f cameraUp(0, 1, 0);
Eigen::Vector3f modelTranslation(0, 0, 0);
Eigen::Vector4f viewport(0, 0, 800, 800);

float currentMouseX;
float currentMouseY;
float mouseDownX;
float mouseDownY;
float mouseDownZ;
Eigen::Quaternionf mouseDownRotation;

void Viewer::init() {

  glfwInit();
  glfwSetTime(0);

  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
  glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
  glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

  glfwWindowHint(GLFW_SAMPLES, 0);
  glfwWindowHint(GLFW_RED_BITS, 8);
  glfwWindowHint(GLFW_GREEN_BITS, 8);
  glfwWindowHint(GLFW_BLUE_BITS, 8);
  glfwWindowHint(GLFW_ALPHA_BITS, 8);
  glfwWindowHint(GLFW_STENCIL_BITS, 8);
  glfwWindowHint(GLFW_DEPTH_BITS, 24);
  glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);

  // glEnable(GL_DEPTH_TEST);
  // glEnable(GL_LIGHTING);

  window = glfwCreateWindow(width, height, "CAD app", nullptr, nullptr);
  glfwMakeContextCurrent(window);

  glViewport(0, 0, width, height);
  glfwSwapInterval(0);
  glfwSwapBuffers(window);

  int windowWidth, windowHeight;
  glfwGetWindowSize(window, &windowWidth, &windowHeight);

  screen = new nanogui::Screen();
  screen->initialize(window, true);

  nanogui::FormHelper *gui = new nanogui::FormHelper(screen);
  nanogui::ref<nanogui::Window> guiWindow = gui->addWindow(Eigen::Vector2i(10, 10), "Main Menu");
  gui->addGroup("Workspace");
  gui->addButton("Load", [&]() { this->load(); });
  // gui->addButton("Save", [&]() { this->save(); });
  gui->addVariable("Wireframe", wireframe);

  screen->setVisible(true);
  screen->performLayout();
}

void Viewer::load() {
  std::string filename = nanogui::file_dialog({
    {"obj", "Wavefront OBJ"}
    }, false);
  std::cout << filename << std::endl;

  if (filename.empty()) {
    return;
  }

  Eigen::MatrixXf V;
  Eigen::MatrixXi F;
  loader.loadObj(filename, V, F);
  mesh.set(V, F);
  // this->mesh.setUv(vertexUvs, faceUvs);

  // core.align_camera_center(data.V,data.F);
}

void Viewer::save() {
  std::cout << "save" << std::endl;
}

void Viewer::computeCameraMatries() {

  modelMatrix = Eigen::Matrix4f::Identity();
  viewMatrix = Eigen::Matrix4f::Identity();
  projMatrix = Eigen::Matrix4f::Identity();

  // Set view parameters
  viewMatrix = control.lookAt(cameraEye, cameraCenter, cameraUp);

  // Set projection paramters
  if (orthographic) {
    float length = (cameraEye - cameraCenter).norm();
    float h = tan(cameraViewAngle/360.0 * M_PI) * (length);
    float left = -h * width / height;
    float right = h * width / height;
    float bottom = -h;
    float top = h;
    projMatrix = control.ortho(left, right, bottom, top, cameraNear, cameraFar);
  } else {
    float fH = tan(cameraViewAngle / 360.0 * M_PI) * cameraNear;
    float fW = fH * width / height;
    float left = -fW;
    float right = fW;
    float bottom = -fH;
    float top = fH;
    projMatrix = control.frustum(left, right, bottom, top, cameraNear, cameraFar);
  }

  // Set model parameters
  modelMatrix = control.quatToMatrix(arcballQuat);
  modelMatrix.topLeftCorner(3,3) *= cameraZoom;
  modelMatrix.topLeftCorner(3,3) *= modelZoom;
  modelMatrix.col(3).head(3) += modelMatrix.topLeftCorner(3,3)*modelTranslation;

}

void Viewer::launch() {
  init();
  setCallbacks();

  std::cout << "Compiling shaders .. ";
  std::cout.flush();
  shaderMesh.initFromFiles("shader_mesh",
    "../src/shader_mesh.vert",
    "../src/shader_mesh.frag",
    "../src/shader_mesh.geom");
  shaderWireframe.initFromFiles("shader_wireframe",
    "../src/shader_wireframe.vert",
    "../src/shader_wireframe.frag");
  std::cout << "done." << std::endl;

  std::string filename = "../bunny.obj";
  Eigen::MatrixXf V;
  Eigen::MatrixXi F;
  loader.loadObj(filename, V, F);
  mesh.set(V, F);

  while (glfwWindowShouldClose(window) == 0 && glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS) {

    glfwPollEvents();
    glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    float ratio;
    int frameWidth, frameHeight;
    glfwGetFramebufferSize(window, &frameWidth, &frameHeight);
    ratio = frameWidth / (float)frameHeight;
    glViewport(0, 0, frameWidth, frameHeight);

    // Set transformaition parameters
    computeCameraMatries();

    Eigen::Vector3f lightPosition(0.0f, 0.30f, 5.0f);
    Eigen::Vector4f civ = (viewMatrix * modelMatrix).inverse() * Eigen::Vector4f(0.0f, 0.0f, 0.0f, 1.0f);
    Eigen::Vector3f cameraLocal = Eigen::Vector3f(civ.head(3));
    Eigen::Vector3f baseColor(0.4f, 0.4f, 0.4f);
    Eigen::Vector3f specularColor(1.0f, 1.0f, 1.0f);

    shaderMesh.bind();

    // vertex shader
    shaderMesh.uploadIndices(mesh.F);
    shaderMesh.uploadAttrib("position", mesh.V);
    shaderMesh.uploadAttrib("normal", mesh.N);

    // geometry shader
    shaderMesh.setUniform("model", modelMatrix);
    shaderMesh.setUniform("view", viewMatrix);
    shaderMesh.setUniform("proj", projMatrix);
    shaderMesh.setUniform("light_position", lightPosition);
    shaderMesh.setUniform("camera_local", cameraLocal);

    // fragment shader
    shaderMesh.setUniform("show_uvs", 0.0f);
    shaderMesh.setUniform("base_color", baseColor);
    shaderMesh.setUniform("specular_color", specularColor);
    // shaderMesh.setUniform("fixed_color", Eigen::Vector4f(1.0, 1.0, 1.0, 1.0));

    glEnable(GL_POLYGON_OFFSET_FILL);
    glPolygonOffset(1.0, 1.0);
    shaderMesh.drawIndexed(GL_TRIANGLES, 0, mesh.F.cols());
    glDisable(GL_POLYGON_OFFSET_FILL);
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

    glEnable(GL_LINE_SMOOTH);
    shaderWireframe.bind();
    shaderWireframe.uploadAttrib("position", mesh.V);
    shaderWireframe.setUniform("color", baseColor);
    shaderWireframe.setUniform("mvp", Eigen::Matrix4f(projMatrix * viewMatrix * modelMatrix));
    shaderWireframe.drawIndexed(GL_LINES, 0, mesh.F.cols());

    glfwPostEmptyEvent();

    // Send texture paramters
    /*
    if (wireframe) {
      glEnable(GL_LINE_SMOOTH);
      glLineWidth(lineWidth);
      glUniform4f(fixedColor, lineColor[0], lineColor[1],
        lineColor[2], 1.0f);
      opengl.drawMesh(false);
      glUniform4f(fixedColor, 0.0f, 0.0f, 0.0f, 0.0f);
    } else {
      glUniform1f(textureFactor, 1.0f);
      opengl.drawMesh(true);
      glUniform1f(textureFactor, 0.0f);
    }
    */

    screen->drawContents();
    screen->drawWidgets();

    glfwSwapBuffers(window);
  }

  glfwTerminate();
}

void Viewer::debug() {
  GLShader mShader;
  mShader.init(
    "a_simple_shader",

    "#version 330\n"
    "uniform mat4 modelViewProj;\n"
    "in vec3 position;\n"
    "void main() {\n"
    "  gl_Position = modelViewProj * vec4(position, 1.0);\n"
    "}",

    "#version 330\n"
    "out vec4 color;\n"
    "uniform float intensity;\n"
    "void main() {\n"
    "  color = vec4(vec3(intensity), 1.0);\n"
    "}"
  );

  Eigen::MatrixXi indices(3, 2);
  indices.col(0) << 0, 1, 2;
  indices.col(1) << 2, 3, 0;

  Eigen::MatrixXf positions(3, 4);
  positions.col(0) << -1, -1, 0;
  positions.col(1) <<  1, -1, 0;
  positions.col(2) <<  1,  1, 0;
  positions.col(3) << -1,  1, 0;

  mShader.bind();
  mShader.uploadIndices(indices);
  mShader.uploadAttrib("position", positions);
  mShader.setUniform("intensity", 0.5f);

  Eigen::Matrix4f mvp;
  mvp.setIdentity();
  mvp.topLeftCorner<3,3>() = Eigen::Matrix3f(Eigen::AngleAxisf((float) glfwGetTime(), Eigen::Vector3f::UnitZ())) * 0.25f;
  mvp.row(0) *= (float) width / (float) height;
  mShader.setUniform("modelViewProj", mvp);
  mShader.drawIndexed(GL_TRIANGLES, 0, 2);

}

void Viewer::setCallbacks() {
  glfwSetKeyCallback(window, [](GLFWwindow *, int key, int scancode, int action, int mods) {
    screen->keyCallbackEvent(key, scancode, action, mods);
  });

  glfwSetCharCallback(window, [](GLFWwindow *, unsigned int codepoint) {
    screen->charCallbackEvent(codepoint);
  });

  glfwSetDropCallback(window, [](GLFWwindow *, int count, const char **filenames) {
    screen->dropCallbackEvent(count, filenames);
  });

  glfwSetMouseButtonCallback(window, [](GLFWwindow *, int button, int action, int modifiers) {
    screen->mouseButtonCallbackEvent(button, action, modifiers);

    if (action == GLFW_PRESS) {
      mouseDown = true;
      Eigen::Vector3f coord = control.project(center, modelMatrix, projMatrix, viewMatrix, viewport);

      mouseDownX = currentMouseX;
      mouseDownY = currentMouseY;
      mouseDownZ = coord[2];
      mouseDownRotation = arcballQuat.normalized();
    } else {
      mouseDown = false;
    }
  // mouseMode = "ROTATION";

  });

  glfwSetCursorPosCallback(window, [](GLFWwindow *, double x, double y) {
    screen->cursorPosCallbackEvent(x, y);

    float mouseX = x;
    float mouseY = y;

    currentMouseX = x;
    currentMouseY = y;

    double speed = 2.0;
    if (mouseDown) {
      std::cout << Eigen::Vector4f(mouseDownX, mouseDownY, mouseX, mouseY) << std::endl;
      Eigen::Quaternionf diffRotation = control.motion(width, height, mouseX, mouseY, mouseDownX, mouseDownY, speed);
      arcballQuat = diffRotation * mouseDownRotation;
    }

  });

  glfwSetScrollCallback(window, [](GLFWwindow *, double x, double y) {
    screen->scrollCallbackEvent(x, y);

    float deltaY = y;
    std::cout << deltaY << std::endl;
    if (deltaY != 0) {
      float mult = (1.0 + ((deltaY>0) ? 1.0 : -1.0) * 0.05);
      const float minZoom = 0.1f;
      cameraZoom = (cameraZoom * mult > minZoom ? cameraZoom * mult : minZoom);
    }

  });

  glfwSetFramebufferSizeCallback(window, [](GLFWwindow *, int width, int height) {
    screen->resizeCallbackEvent(width, height);
  });

}

<commit_msg>Add depth test<commit_after>
#include "viewer.h"

nanogui::Screen *screen = nullptr;
Control control;
Loader loader;

float width = 800;
float height = 800;

bool mouseDown = false;
bool orthographic = false;
bool wireframe = false;
float cameraViewAngle = 45.0;
float cameraNear = 1.0;
float cameraFar = 100.0;
float lineWidth = 0.5f;
float cameraZoom = 3.0f;
float modelZoom = 3.0f;

Eigen::Matrix4f viewMatrix = Eigen::Matrix4f::Identity();
Eigen::Matrix4f projMatrix = Eigen::Matrix4f::Identity();
Eigen::Matrix4f modelMatrix = Eigen::Matrix4f::Identity();
Eigen::Quaternionf arcballQuat = Eigen::Quaternionf::Identity();

Eigen::Vector3f center(0, 1, 0);
Eigen::Vector4f lineColor(1.0f, 1.0f, 1.0f, 1.0f);
Eigen::Vector3f cameraEye(0, 0, 5);
Eigen::Vector3f cameraCenter(0, 1, 0);
Eigen::Vector3f cameraUp(0, 1, 0);
Eigen::Vector3f modelTranslation(0, 0, 0);
Eigen::Vector4f viewport(0, 0, 800, 800);

float currentMouseX;
float currentMouseY;
float mouseDownX;
float mouseDownY;
float mouseDownZ;
Eigen::Quaternionf mouseDownRotation;

void Viewer::init() {

  glfwInit();
  glfwSetTime(0);

  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
  glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
  glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

  glfwWindowHint(GLFW_SAMPLES, 0);
  glfwWindowHint(GLFW_RED_BITS, 8);
  glfwWindowHint(GLFW_GREEN_BITS, 8);
  glfwWindowHint(GLFW_BLUE_BITS, 8);
  glfwWindowHint(GLFW_ALPHA_BITS, 8);
  glfwWindowHint(GLFW_STENCIL_BITS, 8);
  glfwWindowHint(GLFW_DEPTH_BITS, 24);
  glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);

  // glEnable(GL_DEPTH_TEST);
  // glEnable(GL_LIGHTING);

  window = glfwCreateWindow(width, height, "CAD app", nullptr, nullptr);
  glfwMakeContextCurrent(window);

  glViewport(0, 0, width, height);
  glfwSwapInterval(0);
  glfwSwapBuffers(window);

  int windowWidth, windowHeight;
  glfwGetWindowSize(window, &windowWidth, &windowHeight);

  screen = new nanogui::Screen();
  screen->initialize(window, true);

  nanogui::FormHelper *gui = new nanogui::FormHelper(screen);
  nanogui::ref<nanogui::Window> guiWindow = gui->addWindow(Eigen::Vector2i(10, 10), "Main Menu");
  gui->addGroup("Workspace");
  gui->addButton("Load", [&]() { this->load(); });
  // gui->addButton("Save", [&]() { this->save(); });
  gui->addVariable("Wireframe", wireframe);

  screen->setVisible(true);
  screen->performLayout();
}

void Viewer::load() {
  std::string filename = nanogui::file_dialog({
    {"obj", "Wavefront OBJ"}
    }, false);
  std::cout << filename << std::endl;

  if (filename.empty()) {
    return;
  }

  Eigen::MatrixXf V;
  Eigen::MatrixXi F;
  loader.loadObj(filename, V, F);
  mesh.set(V, F);
  // this->mesh.setUv(vertexUvs, faceUvs);

  // core.align_camera_center(data.V,data.F);
}

void Viewer::save() {
  std::cout << "save" << std::endl;
}

void Viewer::computeCameraMatries() {

  modelMatrix = Eigen::Matrix4f::Identity();
  viewMatrix = Eigen::Matrix4f::Identity();
  projMatrix = Eigen::Matrix4f::Identity();

  // Set view parameters
  viewMatrix = control.lookAt(cameraEye, cameraCenter, cameraUp);

  // Set projection paramters
  if (orthographic) {
    float length = (cameraEye - cameraCenter).norm();
    float h = tan(cameraViewAngle/360.0 * M_PI) * (length);
    float left = -h * width / height;
    float right = h * width / height;
    float bottom = -h;
    float top = h;
    projMatrix = control.ortho(left, right, bottom, top, cameraNear, cameraFar);
  } else {
    float fH = tan(cameraViewAngle / 360.0 * M_PI) * cameraNear;
    float fW = fH * width / height;
    float left = -fW;
    float right = fW;
    float bottom = -fH;
    float top = fH;
    projMatrix = control.frustum(left, right, bottom, top, cameraNear, cameraFar);
  }

  // Set model parameters
  modelMatrix = control.quatToMatrix(arcballQuat);
  modelMatrix.topLeftCorner(3,3) *= cameraZoom;
  modelMatrix.topLeftCorner(3,3) *= modelZoom;
  modelMatrix.col(3).head(3) += modelMatrix.topLeftCorner(3,3)*modelTranslation;

}

void Viewer::launch() {
  init();
  setCallbacks();

  std::cout << "Compiling shaders .. ";
  std::cout.flush();
  shaderMesh.initFromFiles("shader_mesh",
    "../src/shader_mesh.vert",
    "../src/shader_mesh.frag",
    "../src/shader_mesh.geom");
  shaderWireframe.initFromFiles("shader_wireframe",
    "../src/shader_wireframe.vert",
    "../src/shader_wireframe.frag");
  std::cout << "done." << std::endl;

  std::string filename = "../bunny.obj";
  Eigen::MatrixXf V;
  Eigen::MatrixXi F;
  loader.loadObj(filename, V, F);
  mesh.set(V, F);

  while (glfwWindowShouldClose(window) == 0 && glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS) {

    glfwPollEvents();
    glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    float ratio;
    int frameWidth, frameHeight;
    glfwGetFramebufferSize(window, &frameWidth, &frameHeight);
    ratio = frameWidth / (float)frameHeight;
    glViewport(0, 0, frameWidth, frameHeight);

    // Set transformaition parameters
    computeCameraMatries();

    glDepthFunc(GL_LEQUAL);
    glEnable(GL_DEPTH_TEST);
    glLineWidth(1.0f);

    Eigen::Vector3f lightPosition(0.0f, 0.30f, 5.0f);
    Eigen::Vector4f civ = (viewMatrix * modelMatrix).inverse() * Eigen::Vector4f(0.0f, 0.0f, 0.0f, 1.0f);
    Eigen::Vector3f cameraLocal = Eigen::Vector3f(civ.head(3));
    Eigen::Vector3f baseColor(0.4f, 0.4f, 0.4f);
    Eigen::Vector3f specularColor(1.0f, 1.0f, 1.0f);

    shaderMesh.bind();

    // vertex shader
    shaderMesh.uploadIndices(mesh.F);
    shaderMesh.uploadAttrib("position", mesh.V);
    shaderMesh.uploadAttrib("normal", mesh.N);

    // geometry shader
    shaderMesh.setUniform("model", modelMatrix);
    shaderMesh.setUniform("view", viewMatrix);
    shaderMesh.setUniform("proj", projMatrix);
    shaderMesh.setUniform("light_position", lightPosition);
    shaderMesh.setUniform("camera_local", cameraLocal);

    // fragment shader
    shaderMesh.setUniform("show_uvs", 0.0f);
    shaderMesh.setUniform("base_color", baseColor);
    shaderMesh.setUniform("specular_color", specularColor);
    // shaderMesh.setUniform("fixed_color", Eigen::Vector4f(1.0, 1.0, 1.0, 1.0));

    glEnable(GL_POLYGON_OFFSET_FILL);
    glPolygonOffset(1.0, 1.0);
    shaderMesh.drawIndexed(GL_TRIANGLES, 0, mesh.F.cols());
    glDisable(GL_POLYGON_OFFSET_FILL);
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

    glEnable(GL_LINE_SMOOTH);
    shaderWireframe.bind();
    shaderWireframe.uploadAttrib("position", mesh.V);
    shaderWireframe.setUniform("color", baseColor);
    shaderWireframe.setUniform("mvp", Eigen::Matrix4f(projMatrix * viewMatrix * modelMatrix));
    shaderWireframe.drawIndexed(GL_LINES, 0, mesh.F.cols());

    glfwPostEmptyEvent();

    // Send texture paramters
    /*
    if (wireframe) {
      glEnable(GL_LINE_SMOOTH);
      glLineWidth(lineWidth);
      glUniform4f(fixedColor, lineColor[0], lineColor[1],
        lineColor[2], 1.0f);
      opengl.drawMesh(false);
      glUniform4f(fixedColor, 0.0f, 0.0f, 0.0f, 0.0f);
    } else {
      glUniform1f(textureFactor, 1.0f);
      opengl.drawMesh(true);
      glUniform1f(textureFactor, 0.0f);
    }
    */

    screen->drawContents();
    screen->drawWidgets();

    glfwSwapBuffers(window);
  }

  glfwTerminate();
}

void Viewer::debug() {
  GLShader mShader;
  mShader.init(
    "a_simple_shader",

    "#version 330\n"
    "uniform mat4 modelViewProj;\n"
    "in vec3 position;\n"
    "void main() {\n"
    "  gl_Position = modelViewProj * vec4(position, 1.0);\n"
    "}",

    "#version 330\n"
    "out vec4 color;\n"
    "uniform float intensity;\n"
    "void main() {\n"
    "  color = vec4(vec3(intensity), 1.0);\n"
    "}"
  );

  Eigen::MatrixXi indices(3, 2);
  indices.col(0) << 0, 1, 2;
  indices.col(1) << 2, 3, 0;

  Eigen::MatrixXf positions(3, 4);
  positions.col(0) << -1, -1, 0;
  positions.col(1) <<  1, -1, 0;
  positions.col(2) <<  1,  1, 0;
  positions.col(3) << -1,  1, 0;

  mShader.bind();
  mShader.uploadIndices(indices);
  mShader.uploadAttrib("position", positions);
  mShader.setUniform("intensity", 0.5f);

  Eigen::Matrix4f mvp;
  mvp.setIdentity();
  mvp.topLeftCorner<3,3>() = Eigen::Matrix3f(Eigen::AngleAxisf((float) glfwGetTime(), Eigen::Vector3f::UnitZ())) * 0.25f;
  mvp.row(0) *= (float) width / (float) height;
  mShader.setUniform("modelViewProj", mvp);
  mShader.drawIndexed(GL_TRIANGLES, 0, 2);

}

void Viewer::setCallbacks() {
  glfwSetKeyCallback(window, [](GLFWwindow *, int key, int scancode, int action, int mods) {
    screen->keyCallbackEvent(key, scancode, action, mods);
  });

  glfwSetCharCallback(window, [](GLFWwindow *, unsigned int codepoint) {
    screen->charCallbackEvent(codepoint);
  });

  glfwSetDropCallback(window, [](GLFWwindow *, int count, const char **filenames) {
    screen->dropCallbackEvent(count, filenames);
  });

  glfwSetMouseButtonCallback(window, [](GLFWwindow *, int button, int action, int modifiers) {
    screen->mouseButtonCallbackEvent(button, action, modifiers);

    if (action == GLFW_PRESS) {
      mouseDown = true;
      Eigen::Vector3f coord = control.project(center, modelMatrix, projMatrix, viewMatrix, viewport);

      mouseDownX = currentMouseX;
      mouseDownY = currentMouseY;
      mouseDownZ = coord[2];
      mouseDownRotation = arcballQuat.normalized();
    } else {
      mouseDown = false;
    }
  // mouseMode = "ROTATION";

  });

  glfwSetCursorPosCallback(window, [](GLFWwindow *, double x, double y) {
    screen->cursorPosCallbackEvent(x, y);

    float mouseX = x;
    float mouseY = y;

    currentMouseX = x;
    currentMouseY = y;

    double speed = 2.0;
    if (mouseDown) {
      std::cout << Eigen::Vector4f(mouseDownX, mouseDownY, mouseX, mouseY) << std::endl;
      Eigen::Quaternionf diffRotation = control.motion(width, height, mouseX, mouseY, mouseDownX, mouseDownY, speed);
      arcballQuat = diffRotation * mouseDownRotation;
    }

  });

  glfwSetScrollCallback(window, [](GLFWwindow *, double x, double y) {
    screen->scrollCallbackEvent(x, y);

    float deltaY = y;
    std::cout << deltaY << std::endl;
    if (deltaY != 0) {
      float mult = (1.0 + ((deltaY>0) ? 1.0 : -1.0) * 0.05);
      const float minZoom = 0.1f;
      cameraZoom = (cameraZoom * mult > minZoom ? cameraZoom * mult : minZoom);
    }

  });

  glfwSetFramebufferSizeCallback(window, [](GLFWwindow *, int width, int height) {
    screen->resizeCallbackEvent(width, height);
  });

}

<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2011.  All rights reserved
 */
#include	"../StroikaPreComp.h"

#include	"Sleep.h"

#include	"ThreadPool.h"

using	namespace	Stroika::Foundation;
using	namespace	Stroika::Foundation::Execution;

class	ThreadPool::MyRunnable_ : public IRunnable {
	public:
		MyRunnable_ (ThreadPool& threadPool)
			: fThreadPool_ (threadPool)
			, fCurTask_ ()
			, fNextTask_ ()
			, fCurTaskUpdateCritSection_ ()
			{
			}

	public:
		ThreadPool::TaskType	GetCurrentTask () const
			{
				AutoCriticalSection critSect (fCurTaskUpdateCritSection_);
				// THIS CODE IS TOO SUBTLE - BUT BECAUSE OF HOW THIS IS CALLED - fNextTask_ will NEVER be in the middle of being updated during this code - so this test is OK
				// Caller is never in the middle of doing a WaitForNextTask - and because we have this lock - we aren't updateing fCurTask_ or fNextTask_ either
				Assert (fCurTask_.IsNull () or fNextTask_.IsNull ());	// one or both must be null
				return fCurTask_.IsNull ()? fNextTask_ : fCurTask_;
			}

	public:
		virtual	void	Run () override
			{
				// For NOW - allow ThreadAbort to just kill this thread. In the future - we may want to implement some sort of restartability

				// Keep grabbing new tasks, and running them
				while (true) {
					{
						fThreadPool_.WaitForNextTask_ (&fNextTask_);			// This will block INDEFINITELY until ThreadAbort throws out or we have a new task to run
						AutoCriticalSection critSect (fCurTaskUpdateCritSection_);
						Assert (not fNextTask_.IsNull ());
						Assert (fCurTask_.IsNull ());
						fCurTask_ = fNextTask_;
						fNextTask_.clear ();
						Assert (not fCurTask_.IsNull ());
						Assert (fNextTask_.IsNull ());
					}
					try {
						fCurTask_->Run ();
						fCurTask_.clear ();
					}
					catch (const ThreadAbortException&) {
						AutoCriticalSection critSect (fCurTaskUpdateCritSection_);
						fCurTask_.clear ();
						throw;	// cancel this thread
					}
					catch (...) {
						AutoCriticalSection critSect (fCurTaskUpdateCritSection_);
						fCurTask_.clear ();
						// other excpetions WARNING WITH DEBUG MESSAGE - but otehrwise - EAT/IGNORE
					}
				}
			}

	private:
		ThreadPool&					fThreadPool_;
		mutable CriticalSection		fCurTaskUpdateCritSection_;
		ThreadPool::TaskType		fCurTask_;
		ThreadPool::TaskType		fNextTask_;

	public:
		DECLARE_USE_BLOCK_ALLOCATION(MyRunnable_);
};

/*
 ********************************************************************************
 ********************************* Execution::ThreadPool ************************
 ********************************************************************************
 */
ThreadPool::ThreadPool (unsigned int nThreads)
	: fCriticalSection_ ()
	, fAborted_ (false)
	, fThreads_ ()
	, fTasks_ ()
	, fTasksAdded_ ()
{
	SetPoolSize (nThreads);
}

unsigned int	ThreadPool::GetPoolSize () const
{
	AutoCriticalSection	critSection (fCriticalSection_);
	return fThreads_.size ();
}

void	ThreadPool::SetPoolSize (unsigned int poolSize)
{
	Require (not fAborted_);
	AutoCriticalSection	critSection (fCriticalSection_);
	fThreads_.reserve (poolSize);
	while (poolSize > fThreads_.size ()) {
		fThreads_.push_back (mkThread_ ());
	}

	if (poolSize < fThreads_.size ()) {
		AssertNotImplemented ();

		// MUST STOP THREADS and WAIT FOR THEM TO BE DONE (OR STORE THEM SOMEPLACE ELSE - NO - I THINK MUST ABORTANDWAIT().  Unsure.
		// For now - just assert!!!

		// TODO:
		//		(1)	HOIRRIBLE - NOW
		fThreads_.resize (poolSize);	// remove some off the end. OK if they are running?
	}

}

void	ThreadPool::AddTask (const TaskType& task)
{
	Require (not fAborted_);
	{
		AutoCriticalSection	critSection (fCriticalSection_);
		fTasks_.push_back (task);
	}

	// Notify any waiting threads to wakeup and claim the next task
	fTasksAdded_.Set ();
}

void	ThreadPool::AbortTask (const TaskType& task, Time::DurationSecondsType timeout)
{
	{
		// First see if its in the Q
		AutoCriticalSection	critSection (fCriticalSection_);
		for (list<TaskType>::iterator i = fTasks_.begin (); i != fTasks_.end (); ++i) {
			if (*i == task) {
				fTasks_.erase (i);
				return;
			}
		}
	}

	// If we got here - its NOT in the task Q, so maybe its already running.
	//
	//

	// TODO:
	//		We walk the list of existing threads and ask each one if its (indirected - running task) is the given one and abort that task.
	//		But that requires we can RESTART an ABORTED thread (or that we remove it from the list - maybe thats better). THat COULD be OK
	//		actually since it involves on API changes and makes sense. The only slight issue is a peformace one but probably for soemthing
	//		quite rare.
	//
	//		Anyhow SB OK for now to just not allow aborting a task which has already started....
	Thread	thread2Kill;
	{
		AutoCriticalSection	critSection (fCriticalSection_);
		for (vector<Thread>::iterator i = fThreads_.begin (); i != fThreads_.end (); ++i) {
			SharedPtr<IRunnable>	tr	=	i->GetRunnable ();
			Assert (dynamic_cast<MyRunnable_*> (tr.get ()) != nullptr);
			SharedPtr<IRunnable>	ct	=	dynamic_cast<MyRunnable_&> (*tr.get ()).GetCurrentTask ();
			if (task == ct) {
				thread2Kill	=	*i;
				*i = mkThread_ ();
				break;
			}
		}
	}
	if (not thread2Kill.GetStatus () != Thread::eNull) {
		thread2Kill.AbortAndWaitForDone (timeout);
	}
}

bool	ThreadPool::IsPresent (const TaskType& task) const
{
	{
		// First see if its in the Q
		AutoCriticalSection	critSection (fCriticalSection_);
		for (list<TaskType>::const_iterator i = fTasks_.begin (); i != fTasks_.end (); ++i) {
			if (*i == task) {
				return true;
			}
		}
	}
	return IsRunning (task);
}

bool	ThreadPool::IsRunning (const TaskType& task) const
{
	Require (not task.IsNull ());
	{
		AutoCriticalSection	critSection (fCriticalSection_);
		for (vector<Thread>::const_iterator i = fThreads_.begin (); i != fThreads_.end (); ++i) {
			SharedPtr<IRunnable>	tr	=	i->GetRunnable ();
			Assert (dynamic_cast<MyRunnable_*> (tr.get ()) != nullptr);
			SharedPtr<IRunnable>	rTask	=	dynamic_cast<MyRunnable_&> (*tr.get ()).GetCurrentTask ();
			if (task == rTask) {
				return true;
			}
		}
	}
	return false;
}

void	ThreadPool::WaitForTask (const TaskType& task, Time::DurationSecondsType timeout) const
{
	// Inefficient / VERY SLOPPY impl
	Time::DurationSecondsType	endAt	=	timeout + Time::GetTickCount ();
	while (true) {
		if (not IsPresent (task)) {
			return;
		}
		Time::DurationSecondsType	remaining	=	timeout - Time::GetTickCount ();
		if (remaining <= 0.0) {
			DoThrow (WaitTimedOutException ());
		}
		Execution::Sleep (min (remaining, 1.0));
	}
}

vector<ThreadPool::TaskType>	ThreadPool::GetTasks () const
{
	vector<ThreadPool::TaskType>	result;
	{
		AutoCriticalSection	critSection (fCriticalSection_);
		result.reserve (fTasks_.size () + fThreads_.size ());
		result.insert (result.begin (), fTasks_.begin (), fTasks_.end ());			// copy pending tasks
		for (vector<Thread>::const_iterator i = fThreads_.begin (); i != fThreads_.end (); ++i) {
			SharedPtr<IRunnable>	tr	=	i->GetRunnable ();
			Assert (dynamic_cast<MyRunnable_*> (tr.get ()) != nullptr);
			SharedPtr<IRunnable>	task	=	dynamic_cast<MyRunnable_&> (*tr.get ()).GetCurrentTask ();
			if (not task.IsNull ()) {
				result.push_back (task);
			}
		}
	}
	return result;
}

vector<ThreadPool::TaskType>	ThreadPool::GetRunningTasks () const
{
	vector<ThreadPool::TaskType>	result;
	{
		AutoCriticalSection	critSection (fCriticalSection_);
		result.reserve (fThreads_.size ());
		for (vector<Thread>::const_iterator i = fThreads_.begin (); i != fThreads_.end (); ++i) {
			SharedPtr<IRunnable>	tr	=	i->GetRunnable ();
			Assert (dynamic_cast<MyRunnable_*> (tr.get ()) != nullptr);
			SharedPtr<IRunnable>	task	=	dynamic_cast<MyRunnable_&> (*tr.get ()).GetCurrentTask ();
			if (not task.IsNull ()) {
				result.push_back (task);
			}
		}
	}
	return result;
}

size_t	ThreadPool::GetTasksCount () const
{
	size_t	count	=	0;
	{
		// First see if its in the Q
		AutoCriticalSection	critSection (fCriticalSection_);
		count += fTasks_.size ();
		for (vector<Thread>::const_iterator i = fThreads_.begin (); i != fThreads_.end (); ++i) {
			SharedPtr<IRunnable>	tr	=	i->GetRunnable ();
			Assert (dynamic_cast<MyRunnable_*> (tr.get ()) != nullptr);
			SharedPtr<IRunnable>	task	=	dynamic_cast<MyRunnable_&> (*tr.get ()).GetCurrentTask ();
			if (not task.IsNull ()) {
				count++;
			}
		}
	}
	return count;
}

void	ThreadPool::WaitForDone (Time::DurationSecondsType timeout) const
{
	Require (fAborted_);
	{
		Time::DurationSecondsType	endAt	=	timeout + Time::GetTickCount ();
		AutoCriticalSection	critSection (fCriticalSection_);
		for (vector<Thread>::const_iterator i = fThreads_.begin (); i != fThreads_.end (); ++i) {
			i->WaitForDone (timeout - Time::GetTickCount ());
		}
	}
}

void	ThreadPool::Abort ()
{
	fAborted_ = true;
	{
		// First see if its in the Q
		AutoCriticalSection	critSection (fCriticalSection_);
		fTasks_.clear ();
		for (vector<Thread>::iterator i = fThreads_.begin (); i != fThreads_.end (); ++i) {
			i->Abort ();
		}
	}
}

void	ThreadPool::AbortAndWaitForDone (Time::DurationSecondsType timeout)
{
	Abort ();
	WaitForDone (timeout);
}

// THIS is called NOT from 'this' - but from the context of an OWNED thread of the pool
void	ThreadPool::WaitForNextTask_ (TaskType* result)
{
	RequireNotNull (result);
	if (fAborted_) {
		Execution::DoThrow (ThreadAbortException ());
	}

	while (true) {
		{
			AutoCriticalSection	critSection (fCriticalSection_);
			if (not fTasks_.empty ()) {
				*result	=	fTasks_.front ();
				fTasks_.pop_front ();
				DbgTrace ("ThreadPool::WaitForNextTask_ () is starting a new task");
				return;
			}
		}

		// Prevent spinwaiting... This event is SET when any new item arrives
		fTasksAdded_.Wait ();
	}
}

Thread		ThreadPool::mkThread_ ()
{
	Thread	t	=	Thread (SharedPtr<IRunnable> (new ThreadPool::MyRunnable_ (*this)));		// ADD MY THREADOBJ
	t.SetThreadName (L"Thread Pool");
	t.Start ();
	return t;
}
<commit_msg>a few Debug::TraceContextBumper and DbgTrace messages checked in (but most commented out) for threadPool debugging<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2011.  All rights reserved
 */
#include	"../StroikaPreComp.h"

#include	"Sleep.h"

#include	"ThreadPool.h"

using	namespace	Stroika::Foundation;
using	namespace	Stroika::Foundation::Execution;

class	ThreadPool::MyRunnable_ : public IRunnable {
	public:
		MyRunnable_ (ThreadPool& threadPool)
			: fThreadPool_ (threadPool)
			, fCurTask_ ()
			, fNextTask_ ()
			, fCurTaskUpdateCritSection_ ()
			{
			}

	public:
		ThreadPool::TaskType	GetCurrentTask () const
			{
				AutoCriticalSection critSect (fCurTaskUpdateCritSection_);
				// THIS CODE IS TOO SUBTLE - BUT BECAUSE OF HOW THIS IS CALLED - fNextTask_ will NEVER be in the middle of being updated during this code - so this test is OK
				// Caller is never in the middle of doing a WaitForNextTask - and because we have this lock - we aren't updateing fCurTask_ or fNextTask_ either
				Assert (fCurTask_.IsNull () or fNextTask_.IsNull ());	// one or both must be null
				return fCurTask_.IsNull ()? fNextTask_ : fCurTask_;
			}

	public:
		virtual	void	Run () override
			{
				// For NOW - allow ThreadAbort to just kill this thread. In the future - we may want to implement some sort of restartability

				// Keep grabbing new tasks, and running them
				while (true) {
					{
						fThreadPool_.WaitForNextTask_ (&fNextTask_);			// This will block INDEFINITELY until ThreadAbort throws out or we have a new task to run
						AutoCriticalSection critSect (fCurTaskUpdateCritSection_);
						Assert (not fNextTask_.IsNull ());
						Assert (fCurTask_.IsNull ());
						fCurTask_ = fNextTask_;
						fNextTask_.clear ();
						Assert (not fCurTask_.IsNull ());
						Assert (fNextTask_.IsNull ());
					}
					try {
						fCurTask_->Run ();
						fCurTask_.clear ();
					}
					catch (const ThreadAbortException&) {
						AutoCriticalSection critSect (fCurTaskUpdateCritSection_);
						fCurTask_.clear ();
						throw;	// cancel this thread
					}
					catch (...) {
						AutoCriticalSection critSect (fCurTaskUpdateCritSection_);
						fCurTask_.clear ();
						// other excpetions WARNING WITH DEBUG MESSAGE - but otehrwise - EAT/IGNORE
					}
				}
			}

	private:
		ThreadPool&					fThreadPool_;
		mutable CriticalSection		fCurTaskUpdateCritSection_;
		ThreadPool::TaskType		fCurTask_;
		ThreadPool::TaskType		fNextTask_;

	public:
		DECLARE_USE_BLOCK_ALLOCATION(MyRunnable_);
};

/*
 ********************************************************************************
 ********************************* Execution::ThreadPool ************************
 ********************************************************************************
 */
ThreadPool::ThreadPool (unsigned int nThreads)
	: fCriticalSection_ ()
	, fAborted_ (false)
	, fThreads_ ()
	, fTasks_ ()
	, fTasksAdded_ ()
{
	SetPoolSize (nThreads);
}

unsigned int	ThreadPool::GetPoolSize () const
{
	AutoCriticalSection	critSection (fCriticalSection_);
	return fThreads_.size ();
}

void	ThreadPool::SetPoolSize (unsigned int poolSize)
{
	Debug::TraceContextBumper ctx (TSTR ("ThreadPool::SetPoolSize"));
	Require (not fAborted_);
	AutoCriticalSection	critSection (fCriticalSection_);
	fThreads_.reserve (poolSize);
	while (poolSize > fThreads_.size ()) {
		fThreads_.push_back (mkThread_ ());
	}

	if (poolSize < fThreads_.size ()) {
		AssertNotImplemented ();

		// MUST STOP THREADS and WAIT FOR THEM TO BE DONE (OR STORE THEM SOMEPLACE ELSE - NO - I THINK MUST ABORTANDWAIT().  Unsure.
		// For now - just assert!!!

		// TODO:
		//		(1)	HOIRRIBLE - NOW
		fThreads_.resize (poolSize);	// remove some off the end. OK if they are running?
	}

}

void	ThreadPool::AddTask (const TaskType& task)
{
	//Debug::TraceContextBumper ctx (TSTR ("ThreadPool::AddTask"));
	Require (not fAborted_);
	{
		AutoCriticalSection	critSection (fCriticalSection_);
		fTasks_.push_back (task);
	}

	// Notify any waiting threads to wakeup and claim the next task
	fTasksAdded_.Set ();
}

void	ThreadPool::AbortTask (const TaskType& task, Time::DurationSecondsType timeout)
{
	Debug::TraceContextBumper ctx (TSTR ("ThreadPool::AbortTask"));
	{
		// First see if its in the Q
		AutoCriticalSection	critSection (fCriticalSection_);
		for (list<TaskType>::iterator i = fTasks_.begin (); i != fTasks_.end (); ++i) {
			if (*i == task) {
				fTasks_.erase (i);
				return;
			}
		}
	}

	// If we got here - its NOT in the task Q, so maybe its already running.
	//
	//

	// TODO:
	//		We walk the list of existing threads and ask each one if its (indirected - running task) is the given one and abort that task.
	//		But that requires we can RESTART an ABORTED thread (or that we remove it from the list - maybe thats better). THat COULD be OK
	//		actually since it involves on API changes and makes sense. The only slight issue is a peformace one but probably for soemthing
	//		quite rare.
	//
	//		Anyhow SB OK for now to just not allow aborting a task which has already started....
	Thread	thread2Kill;
	{
		AutoCriticalSection	critSection (fCriticalSection_);
		for (vector<Thread>::iterator i = fThreads_.begin (); i != fThreads_.end (); ++i) {
			SharedPtr<IRunnable>	tr	=	i->GetRunnable ();
			Assert (dynamic_cast<MyRunnable_*> (tr.get ()) != nullptr);
			SharedPtr<IRunnable>	ct	=	dynamic_cast<MyRunnable_&> (*tr.get ()).GetCurrentTask ();
			if (task == ct) {
				thread2Kill	=	*i;
				*i = mkThread_ ();
				break;
			}
		}
	}
	if (not thread2Kill.GetStatus () != Thread::eNull) {
		thread2Kill.AbortAndWaitForDone (timeout);
	}
}

bool	ThreadPool::IsPresent (const TaskType& task) const
{
	{
		// First see if its in the Q
		AutoCriticalSection	critSection (fCriticalSection_);
		for (list<TaskType>::const_iterator i = fTasks_.begin (); i != fTasks_.end (); ++i) {
			if (*i == task) {
				return true;
			}
		}
	}
	return IsRunning (task);
}

bool	ThreadPool::IsRunning (const TaskType& task) const
{
	Require (not task.IsNull ());
	{
		AutoCriticalSection	critSection (fCriticalSection_);
		for (vector<Thread>::const_iterator i = fThreads_.begin (); i != fThreads_.end (); ++i) {
			SharedPtr<IRunnable>	tr	=	i->GetRunnable ();
			Assert (dynamic_cast<MyRunnable_*> (tr.get ()) != nullptr);
			SharedPtr<IRunnable>	rTask	=	dynamic_cast<MyRunnable_&> (*tr.get ()).GetCurrentTask ();
			if (task == rTask) {
				return true;
			}
		}
	}
	return false;
}

void	ThreadPool::WaitForTask (const TaskType& task, Time::DurationSecondsType timeout) const
{
	Debug::TraceContextBumper ctx (TSTR ("ThreadPool::WaitForTask"));
	// Inefficient / VERY SLOPPY impl
	Time::DurationSecondsType	endAt	=	timeout + Time::GetTickCount ();
	while (true) {
		if (not IsPresent (task)) {
			return;
		}
		Time::DurationSecondsType	remaining	=	timeout - Time::GetTickCount ();
		if (remaining <= 0.0) {
			DoThrow (WaitTimedOutException ());
		}
		Execution::Sleep (min (remaining, 1.0));
	}
}

vector<ThreadPool::TaskType>	ThreadPool::GetTasks () const
{
	vector<ThreadPool::TaskType>	result;
	{
		AutoCriticalSection	critSection (fCriticalSection_);
		result.reserve (fTasks_.size () + fThreads_.size ());
		result.insert (result.begin (), fTasks_.begin (), fTasks_.end ());			// copy pending tasks
		for (vector<Thread>::const_iterator i = fThreads_.begin (); i != fThreads_.end (); ++i) {
			SharedPtr<IRunnable>	tr	=	i->GetRunnable ();
			Assert (dynamic_cast<MyRunnable_*> (tr.get ()) != nullptr);
			SharedPtr<IRunnable>	task	=	dynamic_cast<MyRunnable_&> (*tr.get ()).GetCurrentTask ();
			if (not task.IsNull ()) {
				result.push_back (task);
			}
		}
	}
	return result;
}

vector<ThreadPool::TaskType>	ThreadPool::GetRunningTasks () const
{
	vector<ThreadPool::TaskType>	result;
	{
		AutoCriticalSection	critSection (fCriticalSection_);
		result.reserve (fThreads_.size ());
		for (vector<Thread>::const_iterator i = fThreads_.begin (); i != fThreads_.end (); ++i) {
			SharedPtr<IRunnable>	tr	=	i->GetRunnable ();
			Assert (dynamic_cast<MyRunnable_*> (tr.get ()) != nullptr);
			SharedPtr<IRunnable>	task	=	dynamic_cast<MyRunnable_&> (*tr.get ()).GetCurrentTask ();
			if (not task.IsNull ()) {
				result.push_back (task);
			}
		}
	}
	return result;
}

size_t	ThreadPool::GetTasksCount () const
{
	size_t	count	=	0;
	{
		// First see if its in the Q
		AutoCriticalSection	critSection (fCriticalSection_);
		count += fTasks_.size ();
		for (vector<Thread>::const_iterator i = fThreads_.begin (); i != fThreads_.end (); ++i) {
			SharedPtr<IRunnable>	tr	=	i->GetRunnable ();
			Assert (dynamic_cast<MyRunnable_*> (tr.get ()) != nullptr);
			SharedPtr<IRunnable>	task	=	dynamic_cast<MyRunnable_&> (*tr.get ()).GetCurrentTask ();
			if (not task.IsNull ()) {
				count++;
			}
		}
	}
	return count;
}

void	ThreadPool::WaitForDone (Time::DurationSecondsType timeout) const
{
	Debug::TraceContextBumper ctx (TSTR ("ThreadPool::WaitForDone"));
	Require (fAborted_);
	{
		Time::DurationSecondsType	endAt	=	timeout + Time::GetTickCount ();
		AutoCriticalSection	critSection (fCriticalSection_);
		for (vector<Thread>::const_iterator i = fThreads_.begin (); i != fThreads_.end (); ++i) {
			i->WaitForDone (endAt - Time::GetTickCount ());
		}
	}
}

void	ThreadPool::Abort ()
{
	Debug::TraceContextBumper ctx (TSTR ("ThreadPool::Abort"));
	fAborted_ = true;
	{
		// First see if its in the Q
		AutoCriticalSection	critSection (fCriticalSection_);
		fTasks_.clear ();
		for (vector<Thread>::iterator i = fThreads_.begin (); i != fThreads_.end (); ++i) {
			i->Abort ();
		}
	}
}

void	ThreadPool::AbortAndWaitForDone (Time::DurationSecondsType timeout)
{
	Abort ();
	WaitForDone (timeout);
}

// THIS is called NOT from 'this' - but from the context of an OWNED thread of the pool
void	ThreadPool::WaitForNextTask_ (TaskType* result)
{
	RequireNotNull (result);
	if (fAborted_) {
		Execution::DoThrow (ThreadAbortException ());
	}

	while (true) {
		{
			AutoCriticalSection	critSection (fCriticalSection_);
			if (not fTasks_.empty ()) {
				*result	=	fTasks_.front ();
				fTasks_.pop_front ();
				DbgTrace ("ThreadPool::WaitForNextTask_ () is starting a new task");
				return;
			}
		}

		// Prevent spinwaiting... This event is SET when any new item arrives
		//DbgTrace ("ThreadPool::WaitForNextTask_ () - about to wait for added tasks");
		fTasksAdded_.Wait ();
		//DbgTrace ("ThreadPool::WaitForNextTask_ () - completed wait for added tasks");
	}
}

Thread		ThreadPool::mkThread_ ()
{
	Thread	t	=	Thread (SharedPtr<IRunnable> (new ThreadPool::MyRunnable_ (*this)));		// ADD MY THREADOBJ
	t.SetThreadName (L"Thread Pool");
	t.Start ();
	return t;
}
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright Leiden University Medical Center, Erasmus University Medical
 *  Center and contributors
 *
 *  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.txt
 *
 *  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 "selxCropperComponent.h"
#include "selxCheckTemplateProperties.h"

#include "itkImageFileWriter.h"

namespace selx
{

template< int Dimensionality, class TPixel >
CropperComponent< Dimensionality, TPixel >::CropperComponent( const std::string & name,
                                                              LoggerImpl & logger ) : Superclass( name, logger ) {
  this->m_LabelGeometryImageFilter
    = LabelGeometryImageFilterType::New();
  this->m_LabelGeometryImageFilter->CalculateOrientedBoundingBoxOn();

  this->m_RegionOfInterestImageFilter
    = RegionOfInterestImageFilterType::New();

  this->m_Pad = 0;
}

template< int Dimensionality, class TPixel >
int
CropperComponent< Dimensionality, TPixel >::Accept( typename itkImageInterface< Dimensionality, TPixel >::Pointer component )
{
  this->m_Image = component->GetItkImage();
  this->m_RegionOfInterestImageFilter->SetInput(this->m_Image);
  return 0;
}

template< int Dimensionality, class TPixel >
int
CropperComponent< Dimensionality, TPixel >::Accept( typename itkImageMaskInterface< Dimensionality, unsigned char >::Pointer component )
{
  this->m_Mask = component->GetItkImageMask();
  return 0;
}

template< int Dimensionality, class TPixel >
int
CropperComponent< Dimensionality, TPixel >::Accept( typename itkImageFixedMaskInterface< Dimensionality, unsigned char >::Pointer component )
{
  this->m_Mask = component->GetItkImageFixedMask();
  return 0;
}

template< int Dimensionality, class TPixel >
int
CropperComponent< Dimensionality, TPixel >::Accept( typename itkImageMovingMaskInterface< Dimensionality, unsigned char >::Pointer component )
{
  this->m_Mask = component->GetItkImageMovingMask();
  return 0;
}

template< int Dimensionality, class TPixel >
typename CropperComponent< Dimensionality, TPixel >::ItkImagePointer
CropperComponent< Dimensionality, TPixel >::GetItkImage()
{
  return this->m_RegionOfInterestImageFilter->GetOutput();
}

template< int Dimensionality, class TPixel >
typename CropperComponent< Dimensionality, TPixel >::ItkImagePointer
CropperComponent< Dimensionality, TPixel >::GetItkImageFixed()
{
  return this->GetItkImage();
};

template< int Dimensionality, class TPixel >
typename CropperComponent< Dimensionality, TPixel >::ItkImagePointer
CropperComponent< Dimensionality, TPixel >::GetItkImageMoving()
{
  return this->GetItkImage();
};

template< int Dimensionality, class TPixel >
typename CropperComponent< Dimensionality, TPixel >::ItkImageDomainPointer
CropperComponent< Dimensionality, TPixel >
::GetItkImageDomainFixed()
{
  // Implicitly casted to domain (itk::ImageBase)
  return this->m_RegionOfInterestImageFilter->GetOutput();
}

template< int Dimensionality, class TPixel >
void
CropperComponent< Dimensionality, TPixel >::BeforeUpdate()
{

  this->m_Image->UpdateOutputInformation();
  this->m_Mask->UpdateOutputInformation();

  // Output information must be generated before downstream components are run
  this->m_LabelGeometryImageFilter->SetInput(this->m_Mask);
  this->m_LabelGeometryImageFilter->Update();
  auto boundingBox = this->m_LabelGeometryImageFilter->GetBoundingBox(1);

  typename itk::Index< Dimensionality > start;
  start[0] = std::max(boundingBox.GetElement(0) - this->m_Pad, long(this->m_Image->GetLargestPossibleRegion().GetIndex(0)));
  start[1] = std::max(boundingBox.GetElement(2) - this->m_Pad, long(this->m_Image->GetLargestPossibleRegion().GetIndex(1)));
  if( Dimensionality > 2 ) start[2] = std::max(boundingBox.GetElement(4) - this->m_Pad, long(this->m_Image->GetLargestPossibleRegion().GetIndex(2)));
  if( Dimensionality > 3 ) start[3] = std::max(boundingBox.GetElement(6) - this->m_Pad, long(this->m_Image->GetLargestPossibleRegion().GetIndex(3)));

  {
    std::stringstream ss;
    ss << this->m_Image->GetLargestPossibleRegion();
    this->m_Logger.Log(LogLevel::INF, "{0}: Got image with {1}", this->m_Name, ss.str());
  }

  typename itk::Size< Dimensionality > size;
  size[0] = std::min(boundingBox.GetElement(1) - start[0] + 1 + this->m_Pad, long(this->m_Image->GetLargestPossibleRegion().GetSize(0)) - start[0]);
  size[1] = std::min(boundingBox.GetElement(3) - start[1] + 1 + this->m_Pad, long(this->m_Image->GetLargestPossibleRegion().GetSize(1)) - start[1]);
  if( Dimensionality > 2 ) size[2] = std::min(boundingBox.GetElement(5) - start[2] + 1 + this->m_Pad, long(this->m_Image->GetLargestPossibleRegion().GetSize(2)) - start[2]);
  if( Dimensionality > 3 ) size[3] = std::min(boundingBox.GetElement(7) - start[3] + 1 + this->m_Pad, long(this->m_Image->GetLargestPossibleRegion().GetSize(3)) - start[3]);
  typename ItkImageType::RegionType region(start, size);

  {
    std::stringstream ss;
    ss << region;
    this->m_Logger.Log(LogLevel::INF, "{0}: Cropping image to {1}", this->m_Name, ss.str());
  }

  this->m_RegionOfInterestImageFilter->SetRegionOfInterest(region);
}

template< int Dimensionality, class TPixel >
void
CropperComponent< Dimensionality, TPixel >::Update()
{

}

template< int Dimensionality, class TPixel >
bool
CropperComponent< Dimensionality, TPixel >
::MeetsCriterion( const CriterionType & criterion )
{
  auto status = CheckTemplateProperties( this->TemplateProperties(), criterion );
  if( status == CriterionStatus::Satisfied )
  {
    return true;
  }
  else if( status == CriterionStatus::Failed )
  {
    return false;
  }

  if( criterion.first == "Pad" ) {
    this->m_Pad = std::stoi( criterion.second[0] );
    return true;
  }

  return false;
};

template< int Dimensionality, class TPixel  >
bool
CropperComponent< Dimensionality, TPixel >
::ConnectionsSatisfied() {
  if (!this->InterfaceAcceptor<itkImageInterface<Dimensionality, TPixel >>::GetAccepted()) {
    return false;
  }

  if (!this->InterfaceAcceptor<itkImageMaskInterface<Dimensionality, unsigned char >>::GetAccepted() &&
      !this->InterfaceAcceptor<itkImageFixedMaskInterface<Dimensionality, unsigned char >>::GetAccepted() &&
      !this->InterfaceAcceptor<itkImageMovingMaskInterface<Dimensionality, unsigned char >>::GetAccepted()) {
    return false;
  }

  return true;
}

}
<commit_msg>COMP: Fixed VS errors CropperComponent::BeforeUpdate()<commit_after>/*=========================================================================
 *
 *  Copyright Leiden University Medical Center, Erasmus University Medical
 *  Center and contributors
 *
 *  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.txt
 *
 *  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 "selxCropperComponent.h"
#include "selxCheckTemplateProperties.h"

#include "itkImageFileWriter.h"

namespace selx
{

template< int Dimensionality, class TPixel >
CropperComponent< Dimensionality, TPixel >::CropperComponent( const std::string & name,
                                                              LoggerImpl & logger ) : Superclass( name, logger ) {
  this->m_LabelGeometryImageFilter
    = LabelGeometryImageFilterType::New();
  this->m_LabelGeometryImageFilter->CalculateOrientedBoundingBoxOn();

  this->m_RegionOfInterestImageFilter
    = RegionOfInterestImageFilterType::New();

  this->m_Pad = 0;
}

template< int Dimensionality, class TPixel >
int
CropperComponent< Dimensionality, TPixel >::Accept( typename itkImageInterface< Dimensionality, TPixel >::Pointer component )
{
  this->m_Image = component->GetItkImage();
  this->m_RegionOfInterestImageFilter->SetInput(this->m_Image);
  return 0;
}

template< int Dimensionality, class TPixel >
int
CropperComponent< Dimensionality, TPixel >::Accept( typename itkImageMaskInterface< Dimensionality, unsigned char >::Pointer component )
{
  this->m_Mask = component->GetItkImageMask();
  return 0;
}

template< int Dimensionality, class TPixel >
int
CropperComponent< Dimensionality, TPixel >::Accept( typename itkImageFixedMaskInterface< Dimensionality, unsigned char >::Pointer component )
{
  this->m_Mask = component->GetItkImageFixedMask();
  return 0;
}

template< int Dimensionality, class TPixel >
int
CropperComponent< Dimensionality, TPixel >::Accept( typename itkImageMovingMaskInterface< Dimensionality, unsigned char >::Pointer component )
{
  this->m_Mask = component->GetItkImageMovingMask();
  return 0;
}

template< int Dimensionality, class TPixel >
typename CropperComponent< Dimensionality, TPixel >::ItkImagePointer
CropperComponent< Dimensionality, TPixel >::GetItkImage()
{
  return this->m_RegionOfInterestImageFilter->GetOutput();
}

template< int Dimensionality, class TPixel >
typename CropperComponent< Dimensionality, TPixel >::ItkImagePointer
CropperComponent< Dimensionality, TPixel >::GetItkImageFixed()
{
  return this->GetItkImage();
};

template< int Dimensionality, class TPixel >
typename CropperComponent< Dimensionality, TPixel >::ItkImagePointer
CropperComponent< Dimensionality, TPixel >::GetItkImageMoving()
{
  return this->GetItkImage();
};

template< int Dimensionality, class TPixel >
typename CropperComponent< Dimensionality, TPixel >::ItkImageDomainPointer
CropperComponent< Dimensionality, TPixel >
::GetItkImageDomainFixed()
{
  // Implicitly casted to domain (itk::ImageBase)
  return this->m_RegionOfInterestImageFilter->GetOutput();
}

template< int Dimensionality, class TPixel >
void
CropperComponent< Dimensionality, TPixel >::BeforeUpdate()
{

  this->m_Image->UpdateOutputInformation();
  this->m_Mask->UpdateOutputInformation();

  // Output information must be generated before downstream components are run
  this->m_LabelGeometryImageFilter->SetInput(this->m_Mask);
  this->m_LabelGeometryImageFilter->Update();
  const auto boundingBox = this->m_LabelGeometryImageFilter->GetBoundingBox(1);
  const auto& largestPossibleRegion = this->m_Image->GetLargestPossibleRegion();

  {
    std::stringstream ss;
    ss << largestPossibleRegion;
    this->m_Logger.Log(LogLevel::INF, "{0}: Got image with {1}", this->m_Name, ss.str());
  }

  itk::Index< Dimensionality > start;
  itk::Size< Dimensionality > size;

  for (unsigned i{ 0 }; i < Dimensionality; ++i)
  {
    start[i] = std::max<itk::IndexValueType>(
      boundingBox.GetElement(2 * i) - this->m_Pad, largestPossibleRegion.GetIndex(i));
    size[i] = std::min<itk::IndexValueType>(
      boundingBox.GetElement(2 * i + 1) - start[i] + 1 + this->m_Pad, largestPossibleRegion.GetSize(i) - start[i]);
  }

  const typename ItkImageType::RegionType croppedRegion(start, size);

  {
    std::stringstream ss;
    ss << croppedRegion;
    this->m_Logger.Log(LogLevel::INF, "{0}: Cropping image to {1}", this->m_Name, ss.str());
  }

  this->m_RegionOfInterestImageFilter->SetRegionOfInterest(croppedRegion);
}

template< int Dimensionality, class TPixel >
void
CropperComponent< Dimensionality, TPixel >::Update()
{

}

template< int Dimensionality, class TPixel >
bool
CropperComponent< Dimensionality, TPixel >
::MeetsCriterion( const CriterionType & criterion )
{
  auto status = CheckTemplateProperties( this->TemplateProperties(), criterion );
  if( status == CriterionStatus::Satisfied )
  {
    return true;
  }
  else if( status == CriterionStatus::Failed )
  {
    return false;
  }

  if( criterion.first == "Pad" ) {
    this->m_Pad = std::stoi( criterion.second[0] );
    return true;
  }

  return false;
};

template< int Dimensionality, class TPixel  >
bool
CropperComponent< Dimensionality, TPixel >
::ConnectionsSatisfied() {
  if (!this->InterfaceAcceptor<itkImageInterface<Dimensionality, TPixel >>::GetAccepted()) {
    return false;
  }

  if (!this->InterfaceAcceptor<itkImageMaskInterface<Dimensionality, unsigned char >>::GetAccepted() &&
      !this->InterfaceAcceptor<itkImageFixedMaskInterface<Dimensionality, unsigned char >>::GetAccepted() &&
      !this->InterfaceAcceptor<itkImageMovingMaskInterface<Dimensionality, unsigned char >>::GetAccepted()) {
    return false;
  }

  return true;
}

}
<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2014 Torus Knot Software Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/

#include "OgreRoot.h"
#include "OgreException.h"
#include "OgreLogManager.h"
#include "OgreStringConverter.h"
#include "OgreWindowEventUtilities.h"

#include "OgreGLRenderSystemCommon.h"

#include "OgreAndroidEGLSupport.h"
#include "OgreAndroidEGLWindow.h"
#include "OgreViewport.h"

#include <iostream>
#include <algorithm>
#include <climits>

namespace Ogre {
    AndroidEGLWindow::AndroidEGLWindow(AndroidEGLSupport *glsupport)
        : EGLWindow(glsupport),
          mMaxBufferSize(32),
          mMinBufferSize(16),
          mMaxDepthSize(16),
          mMaxStencilSize(0),
          mMSAA(0),
          mCSAA(0),
          mPreserveContext(false)
    {
    }

    void AndroidEGLWindow::getLeftAndTopFromNativeWindow( int & left, int & top, uint width, uint height )
    {
        // We don't have a native window.... but I think all android windows are origined
        left = top = 0;
    }

    void AndroidEGLWindow::initNativeCreatedWindow(const NameValuePairList *miscParams)
    {
    }

    void AndroidEGLWindow::createNativeWindow( int &left, int &top, uint &width, uint &height, String &title )
    {
    }

    void AndroidEGLWindow::reposition( int left, int top )
    {
    }

    void AndroidEGLWindow::resize(uint width, uint height)
    {
    }

    void AndroidEGLWindow::windowMovedOrResized()
    {
        if(mActive)
        {
            // When using GPU rendering for Android UI the os creates a context in the main thread
            // Now we have 2 choices create OGRE in its own thread or set our context current before doing
            // anything else. I put this code here because this function called before any rendering is done.
            // Because the events for screen rotation / resizing did not worked on all devices it is the best way
            // to query the correct dimensions.
            mContext->setCurrent();
            eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, (EGLint*)&mWidth);
            eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, (EGLint*)&mHeight);

            // Notify viewports of resize
            ViewportList::iterator it = mViewportList.begin();
            while( it != mViewportList.end() )
                (*it++).second->_updateDimensions();
        }
    }

    void AndroidEGLWindow::switchFullScreen(bool fullscreen)
    {

    }

    void AndroidEGLWindow::create(const String& name, uint width, uint height,
                               bool fullScreen, const NameValuePairList *miscParams)
    {
        mName = name;
        mWidth = width;
        mHeight = height;
        mLeft = 0;
        mTop = 0;
        mIsFullScreen = fullScreen;
        void* eglContext = NULL;
        AConfiguration* config = NULL;
        bool preserveContextOpt = false;

        if (miscParams)
        {
            NameValuePairList::const_iterator opt;
            NameValuePairList::const_iterator end = miscParams->end();

            if ((opt = miscParams->find("currentGLContext")) != end &&
                StringConverter::parseBool(opt->second))
            {
                eglContext = eglGetCurrentContext();
                if (!eglContext)
                {
                    OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
                                "currentGLContext was specified with no current GL context",
                                "EGLWindow::create");
                }

                mEglSurface = eglGetCurrentSurface(EGL_DRAW);
                mEglDisplay = eglGetCurrentDisplay();
            }

            if((opt = miscParams->find("externalWindowHandle")) != end)
            {
                mWindow = (ANativeWindow*)(Ogre::StringConverter::parseSizeT(opt->second));
            }

            if((opt = miscParams->find("androidConfig")) != end)
            {
                config = (AConfiguration*)(Ogre::StringConverter::parseSizeT(opt->second));
            }

            int ctxHandle = -1;
            if((opt = miscParams->find("externalGLContext")) != end)
            {
                mIsExternalGLControl = true;
                ctxHandle = Ogre::StringConverter::parseInt(opt->second);
            }

            if((opt = miscParams->find("maxColourBufferSize")) != end)
            {
                mMaxBufferSize = Ogre::StringConverter::parseInt(opt->second);
            }

            if((opt = miscParams->find("maxDepthBufferSize")) != end)
            {
                mMaxDepthSize = Ogre::StringConverter::parseInt(opt->second);
            }

            if((opt = miscParams->find("maxStencilBufferSize")) != end)
            {
                mMaxStencilSize = Ogre::StringConverter::parseInt(opt->second);
            }

            if((opt = miscParams->find("minColourBufferSize")) != end)
            {
                mMinBufferSize = Ogre::StringConverter::parseInt(opt->second);
                if (mMinBufferSize > mMaxBufferSize) mMinBufferSize = mMaxBufferSize;
            }

            if((opt = miscParams->find("MSAA")) != end)
            {
                mMSAA = Ogre::StringConverter::parseInt(opt->second);
            }

            if((opt = miscParams->find("CSAA")) != end)
            {
                mCSAA = Ogre::StringConverter::parseInt(opt->second);
            }

            if ((opt = miscParams->find("preserveContext")) != end &&
                StringConverter::parseBool(opt->second))
            {
                preserveContextOpt = true;
            }
        }

        initNativeCreatedWindow(miscParams);

        if (mEglSurface)
        {
            mEglConfig = mGLSupport->getGLConfigFromDrawable (mEglSurface, &width, &height);
        }

        if (!mEglConfig && eglContext)
        {
            mEglConfig = mGLSupport->getGLConfigFromContext(eglContext);

            if (!mEglConfig)
            {
                // This should never happen.
                OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
                            "Unexpected failure to determine a EGLFBConfig",
                            "EGLWindow::create");
            }
        }

        mIsExternal = (mEglSurface != 0);

        if (!mEglConfig)
        {
            _createInternalResources(mWindow, config);
            mHwGamma = false;
        }

        mContext = createEGLContext();
        mContext->setCurrent();

        eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, (EGLint*)&mWidth);
        eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, (EGLint*)&mHeight);
        EGL_CHECK_ERROR

        mActive = true;
        mVisible = true;
        mClosed = false;
        mPreserveContext = preserveContextOpt;
    }

    void AndroidEGLWindow::_destroyInternalResources()
    {
        if(mClosed)
            return;

        if (!mPreserveContext)
        {
            mContext->setCurrent();

            static_cast<GLRenderSystemCommon*>(Ogre::Root::getSingletonPtr()->getRenderSystem())->notifyOnContextLost();
            mContext->_destroyInternalResources();
        }

        eglDestroySurface(mEglDisplay, mEglSurface);
        EGL_CHECK_ERROR

        eglTerminate(mEglDisplay);
        EGL_CHECK_ERROR

        mEglDisplay = 0;
        mEglSurface = 0;

        mActive = false;
        mVisible = false;
        mClosed = true;
    }

    void AndroidEGLWindow::_createInternalResources(NativeWindowType window, AConfiguration* config)
    {
        mWindow = window;

        if (mPreserveContext)
        {
            mEglDisplay = mGLSupport->getGLDisplay();
            mEglSurface = createSurfaceFromWindow(mEglDisplay, mWindow);
            static_cast<EGLContext*>(mContext)->_updateInternalResources(mEglDisplay, mEglConfig, mEglSurface);
        }
        else
        {
            int minAttribs[] = {
                EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
                EGL_BUFFER_SIZE, mMinBufferSize,
                EGL_DEPTH_SIZE, 16,
                EGL_NONE
            };

            int maxAttribs[] = {
                EGL_BUFFER_SIZE, mMaxBufferSize,
                EGL_DEPTH_SIZE, mMaxDepthSize,
                EGL_STENCIL_SIZE, mMaxStencilSize,
                EGL_NONE
            };

            bool bAASuccess = false;
            if (mCSAA)
            {
                try
                {
                    int CSAAminAttribs[] = {
                        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
                        EGL_BUFFER_SIZE, mMinBufferSize,
                        EGL_DEPTH_SIZE, 16,
                        EGL_COVERAGE_BUFFERS_NV, 1,
                        EGL_COVERAGE_SAMPLES_NV, mCSAA,
                        EGL_NONE
                    };
                    int CSAAmaxAttribs[] = {
                        EGL_BUFFER_SIZE, mMaxBufferSize,
                        EGL_DEPTH_SIZE, mMaxDepthSize,
                        EGL_STENCIL_SIZE, mMaxStencilSize,
                        EGL_COVERAGE_BUFFERS_NV, 1,
                        EGL_COVERAGE_SAMPLES_NV, mCSAA,
                        EGL_NONE
                    };
                    mEglConfig = mGLSupport->selectGLConfig(CSAAminAttribs, CSAAmaxAttribs);
                    bAASuccess = true;
                }
                catch (Exception& e)
                {
                    LogManager::getSingleton().logMessage("AndroidEGLWindow::_createInternalResources: setting CSAA failed");
                }
            }

            if (mMSAA && !bAASuccess)
            {
                try
                {
                    int MSAAminAttribs[] = {
                        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
                        EGL_BUFFER_SIZE, mMinBufferSize,
                        EGL_DEPTH_SIZE, 16,
                        EGL_SAMPLE_BUFFERS, 1,
                        EGL_SAMPLES, mMSAA,
                        EGL_NONE
                    };
                    int MSAAmaxAttribs[] = {
                        EGL_BUFFER_SIZE, mMaxBufferSize,
                        EGL_DEPTH_SIZE, mMaxDepthSize,
                        EGL_STENCIL_SIZE, mMaxStencilSize,
                        EGL_SAMPLE_BUFFERS, 1,
                        EGL_SAMPLES, mMSAA,
                        EGL_NONE
                    };
                    mEglConfig = mGLSupport->selectGLConfig(MSAAminAttribs, MSAAmaxAttribs);
                    bAASuccess = true;
                }
                catch (Exception& e)
                {
                    LogManager::getSingleton().logMessage("AndroidEGLWindow::_createInternalResources: setting MSAA failed");
                }
            }

            mEglDisplay = mGLSupport->getGLDisplay();
            if (!bAASuccess) mEglConfig = mGLSupport->selectGLConfig(minAttribs, maxAttribs);

            EGLint format;
            eglGetConfigAttrib(mEglDisplay, mEglConfig, EGL_NATIVE_VISUAL_ID, &format);
            EGL_CHECK_ERROR

                ANativeWindow_setBuffersGeometry(mWindow, 0, 0, format);

            mEglSurface = createSurfaceFromWindow(mEglDisplay, mWindow);

            if (config)
            {
                bool isLandscape = (int)AConfiguration_getOrientation(config) == 2;
                mGLSupport->setConfigOption("Orientation", isLandscape ? "Landscape" : "Portrait");
            }
        }

        if(mContext)
        {
            mActive = true;
            mVisible = true;
            mClosed = false;

            if (!mPreserveContext)
            {
                mContext->_createInternalResources(mEglDisplay, mEglConfig, mEglSurface, NULL);

                static_cast<GLRenderSystemCommon*>(Ogre::Root::getSingletonPtr()->getRenderSystem())->resetRenderer(this);
            }
        }
    }
}
<commit_msg>fix build with NDK11+: add missing include<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2014 Torus Knot Software Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/

#include "OgreRoot.h"
#include "OgreException.h"
#include "OgreLogManager.h"
#include "OgreStringConverter.h"
#include "OgreWindowEventUtilities.h"

#include "OgreGLRenderSystemCommon.h"

#include "OgreAndroidEGLSupport.h"
#include "OgreAndroidEGLWindow.h"
#include "OgreViewport.h"

#include <android/native_window.h>

#include <iostream>
#include <algorithm>
#include <climits>

namespace Ogre {
    AndroidEGLWindow::AndroidEGLWindow(AndroidEGLSupport *glsupport)
        : EGLWindow(glsupport),
          mMaxBufferSize(32),
          mMinBufferSize(16),
          mMaxDepthSize(16),
          mMaxStencilSize(0),
          mMSAA(0),
          mCSAA(0),
          mPreserveContext(false)
    {
    }

    void AndroidEGLWindow::getLeftAndTopFromNativeWindow( int & left, int & top, uint width, uint height )
    {
        // We don't have a native window.... but I think all android windows are origined
        left = top = 0;
    }

    void AndroidEGLWindow::initNativeCreatedWindow(const NameValuePairList *miscParams)
    {
    }

    void AndroidEGLWindow::createNativeWindow( int &left, int &top, uint &width, uint &height, String &title )
    {
    }

    void AndroidEGLWindow::reposition( int left, int top )
    {
    }

    void AndroidEGLWindow::resize(uint width, uint height)
    {
    }

    void AndroidEGLWindow::windowMovedOrResized()
    {
        if(mActive)
        {
            // When using GPU rendering for Android UI the os creates a context in the main thread
            // Now we have 2 choices create OGRE in its own thread or set our context current before doing
            // anything else. I put this code here because this function called before any rendering is done.
            // Because the events for screen rotation / resizing did not worked on all devices it is the best way
            // to query the correct dimensions.
            mContext->setCurrent();
            eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, (EGLint*)&mWidth);
            eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, (EGLint*)&mHeight);

            // Notify viewports of resize
            ViewportList::iterator it = mViewportList.begin();
            while( it != mViewportList.end() )
                (*it++).second->_updateDimensions();
        }
    }

    void AndroidEGLWindow::switchFullScreen(bool fullscreen)
    {

    }

    void AndroidEGLWindow::create(const String& name, uint width, uint height,
                               bool fullScreen, const NameValuePairList *miscParams)
    {
        mName = name;
        mWidth = width;
        mHeight = height;
        mLeft = 0;
        mTop = 0;
        mIsFullScreen = fullScreen;
        void* eglContext = NULL;
        AConfiguration* config = NULL;
        bool preserveContextOpt = false;

        if (miscParams)
        {
            NameValuePairList::const_iterator opt;
            NameValuePairList::const_iterator end = miscParams->end();

            if ((opt = miscParams->find("currentGLContext")) != end &&
                StringConverter::parseBool(opt->second))
            {
                eglContext = eglGetCurrentContext();
                if (!eglContext)
                {
                    OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
                                "currentGLContext was specified with no current GL context",
                                "EGLWindow::create");
                }

                mEglSurface = eglGetCurrentSurface(EGL_DRAW);
                mEglDisplay = eglGetCurrentDisplay();
            }

            if((opt = miscParams->find("externalWindowHandle")) != end)
            {
                mWindow = (ANativeWindow*)(Ogre::StringConverter::parseSizeT(opt->second));
            }

            if((opt = miscParams->find("androidConfig")) != end)
            {
                config = (AConfiguration*)(Ogre::StringConverter::parseSizeT(opt->second));
            }

            int ctxHandle = -1;
            if((opt = miscParams->find("externalGLContext")) != end)
            {
                mIsExternalGLControl = true;
                ctxHandle = Ogre::StringConverter::parseInt(opt->second);
            }

            if((opt = miscParams->find("maxColourBufferSize")) != end)
            {
                mMaxBufferSize = Ogre::StringConverter::parseInt(opt->second);
            }

            if((opt = miscParams->find("maxDepthBufferSize")) != end)
            {
                mMaxDepthSize = Ogre::StringConverter::parseInt(opt->second);
            }

            if((opt = miscParams->find("maxStencilBufferSize")) != end)
            {
                mMaxStencilSize = Ogre::StringConverter::parseInt(opt->second);
            }

            if((opt = miscParams->find("minColourBufferSize")) != end)
            {
                mMinBufferSize = Ogre::StringConverter::parseInt(opt->second);
                if (mMinBufferSize > mMaxBufferSize) mMinBufferSize = mMaxBufferSize;
            }

            if((opt = miscParams->find("MSAA")) != end)
            {
                mMSAA = Ogre::StringConverter::parseInt(opt->second);
            }

            if((opt = miscParams->find("CSAA")) != end)
            {
                mCSAA = Ogre::StringConverter::parseInt(opt->second);
            }

            if ((opt = miscParams->find("preserveContext")) != end &&
                StringConverter::parseBool(opt->second))
            {
                preserveContextOpt = true;
            }
        }

        initNativeCreatedWindow(miscParams);

        if (mEglSurface)
        {
            mEglConfig = mGLSupport->getGLConfigFromDrawable (mEglSurface, &width, &height);
        }

        if (!mEglConfig && eglContext)
        {
            mEglConfig = mGLSupport->getGLConfigFromContext(eglContext);

            if (!mEglConfig)
            {
                // This should never happen.
                OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
                            "Unexpected failure to determine a EGLFBConfig",
                            "EGLWindow::create");
            }
        }

        mIsExternal = (mEglSurface != 0);

        if (!mEglConfig)
        {
            _createInternalResources(mWindow, config);
            mHwGamma = false;
        }

        mContext = createEGLContext();
        mContext->setCurrent();

        eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, (EGLint*)&mWidth);
        eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, (EGLint*)&mHeight);
        EGL_CHECK_ERROR

        mActive = true;
        mVisible = true;
        mClosed = false;
        mPreserveContext = preserveContextOpt;
    }

    void AndroidEGLWindow::_destroyInternalResources()
    {
        if(mClosed)
            return;

        if (!mPreserveContext)
        {
            mContext->setCurrent();

            static_cast<GLRenderSystemCommon*>(Ogre::Root::getSingletonPtr()->getRenderSystem())->notifyOnContextLost();
            mContext->_destroyInternalResources();
        }

        eglDestroySurface(mEglDisplay, mEglSurface);
        EGL_CHECK_ERROR

        eglTerminate(mEglDisplay);
        EGL_CHECK_ERROR

        mEglDisplay = 0;
        mEglSurface = 0;

        mActive = false;
        mVisible = false;
        mClosed = true;
    }

    void AndroidEGLWindow::_createInternalResources(NativeWindowType window, AConfiguration* config)
    {
        mWindow = window;

        if (mPreserveContext)
        {
            mEglDisplay = mGLSupport->getGLDisplay();
            mEglSurface = createSurfaceFromWindow(mEglDisplay, mWindow);
            static_cast<EGLContext*>(mContext)->_updateInternalResources(mEglDisplay, mEglConfig, mEglSurface);
        }
        else
        {
            int minAttribs[] = {
                EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
                EGL_BUFFER_SIZE, mMinBufferSize,
                EGL_DEPTH_SIZE, 16,
                EGL_NONE
            };

            int maxAttribs[] = {
                EGL_BUFFER_SIZE, mMaxBufferSize,
                EGL_DEPTH_SIZE, mMaxDepthSize,
                EGL_STENCIL_SIZE, mMaxStencilSize,
                EGL_NONE
            };

            bool bAASuccess = false;
            if (mCSAA)
            {
                try
                {
                    int CSAAminAttribs[] = {
                        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
                        EGL_BUFFER_SIZE, mMinBufferSize,
                        EGL_DEPTH_SIZE, 16,
                        EGL_COVERAGE_BUFFERS_NV, 1,
                        EGL_COVERAGE_SAMPLES_NV, mCSAA,
                        EGL_NONE
                    };
                    int CSAAmaxAttribs[] = {
                        EGL_BUFFER_SIZE, mMaxBufferSize,
                        EGL_DEPTH_SIZE, mMaxDepthSize,
                        EGL_STENCIL_SIZE, mMaxStencilSize,
                        EGL_COVERAGE_BUFFERS_NV, 1,
                        EGL_COVERAGE_SAMPLES_NV, mCSAA,
                        EGL_NONE
                    };
                    mEglConfig = mGLSupport->selectGLConfig(CSAAminAttribs, CSAAmaxAttribs);
                    bAASuccess = true;
                }
                catch (Exception& e)
                {
                    LogManager::getSingleton().logMessage("AndroidEGLWindow::_createInternalResources: setting CSAA failed");
                }
            }

            if (mMSAA && !bAASuccess)
            {
                try
                {
                    int MSAAminAttribs[] = {
                        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
                        EGL_BUFFER_SIZE, mMinBufferSize,
                        EGL_DEPTH_SIZE, 16,
                        EGL_SAMPLE_BUFFERS, 1,
                        EGL_SAMPLES, mMSAA,
                        EGL_NONE
                    };
                    int MSAAmaxAttribs[] = {
                        EGL_BUFFER_SIZE, mMaxBufferSize,
                        EGL_DEPTH_SIZE, mMaxDepthSize,
                        EGL_STENCIL_SIZE, mMaxStencilSize,
                        EGL_SAMPLE_BUFFERS, 1,
                        EGL_SAMPLES, mMSAA,
                        EGL_NONE
                    };
                    mEglConfig = mGLSupport->selectGLConfig(MSAAminAttribs, MSAAmaxAttribs);
                    bAASuccess = true;
                }
                catch (Exception& e)
                {
                    LogManager::getSingleton().logMessage("AndroidEGLWindow::_createInternalResources: setting MSAA failed");
                }
            }

            mEglDisplay = mGLSupport->getGLDisplay();
            if (!bAASuccess) mEglConfig = mGLSupport->selectGLConfig(minAttribs, maxAttribs);

            EGLint format;
            eglGetConfigAttrib(mEglDisplay, mEglConfig, EGL_NATIVE_VISUAL_ID, &format);
            EGL_CHECK_ERROR

                ANativeWindow_setBuffersGeometry(mWindow, 0, 0, format);

            mEglSurface = createSurfaceFromWindow(mEglDisplay, mWindow);

            if (config)
            {
                bool isLandscape = (int)AConfiguration_getOrientation(config) == 2;
                mGLSupport->setConfigOption("Orientation", isLandscape ? "Landscape" : "Portrait");
            }
        }

        if(mContext)
        {
            mActive = true;
            mVisible = true;
            mClosed = false;

            if (!mPreserveContext)
            {
                mContext->_createInternalResources(mEglDisplay, mEglConfig, mEglSurface, NULL);

                static_cast<GLRenderSystemCommon*>(Ogre::Root::getSingletonPtr()->getRenderSystem())->resetRenderer(this);
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2016, Matt Godbolt
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#include "seasocks/ToString.h"

#include "catch.hpp"

using namespace seasocks;

TEST_CASE("insensitiveToLocale", "[toStringTests]") {
    CHECK(toString("1234") == "1234");
    auto prev = std::locale::global(std::locale("en_US.utf8"));
    CHECK(toString("1234") == "1234"); // locale-dependent could have been 1,234
    std::locale::global(std::locale(""));
    CHECK(toString("1234") == "1234"); // locale-dependent could have been 1,234
    std::locale::global(prev);
}
<commit_msg>Fix the tests for toString so they really show bug 28 was fixed. Closes #28<commit_after>// Copyright (c) 2013-2016, Matt Godbolt
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#include "seasocks/ToString.h"

#include "catch.hpp"

using namespace seasocks;

TEST_CASE("insensitiveToLocale", "[toStringTests]") {
    CHECK(toString(1234) == "1234");
    auto prev = std::locale::global(std::locale("en_US.utf8"));
    CHECK(toString(1234) == "1234"); // locale-dependent could have been 1,234
    std::locale::global(std::locale(""));
    CHECK(toString(1234) == "1234"); // locale-dependent could have been 1,234
    std::locale::global(prev);
}
<|endoftext|>


<commit_before>/******************************************************************************
* Copyright (c) 2011, Michael P. Gerlek (mpg@flaxen.com)
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following
* conditions are met:
*
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in
*       the documentation and/or other materials provided
*       with the distribution.
*     * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the
*       names of its contributors may be used to endorse or promote
*       products derived from this software without specific prior
*       written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
****************************************************************************/

#include <libpc/filters/ChipperIterator.hpp>

namespace libpc { namespace filters {

ChipperSequentialIterator::ChipperSequentialIterator(Chipper const& filter)
    : libpc::FilterSequentialIterator(filter)
    , m_chipper(filter)
    , m_currentBlockId(0)
    , m_currentPointCount(0)
{
    const_cast<Chipper&>(m_chipper).Chip();
    return;
}

boost::uint64_t ChipperSequentialIterator::skipImpl(boost::uint64_t count)
{
    return naiveSkipImpl(count);
}

boost::uint32_t ChipperSequentialIterator::readImpl(PointBuffer& buffer)
{
    // The client has asked us for dstData.getCapacity() points.
    // We will read from our previous stage until we get that amount (or
    // until the previous stage runs out of points).

    buffer.setNumPoints(0);

    if (m_currentBlockId == m_chipper.GetBlockCount())
        return 0; // we're done.

    filters::chipper::Block const& block = m_chipper.GetBlock(m_currentBlockId);
    std::size_t numPointsThisBlock = block.GetIDs().size();
    m_currentPointCount = m_currentPointCount + numPointsThisBlock;

    if (buffer.getCapacity() < numPointsThisBlock)
    {
        // FIXME: Expand the buffer?
        throw libpc_error("Buffer not large enough to hold block!");
    }
    block.GetBuffer(m_chipper.getPrevStage(), buffer, m_currentBlockId);

    // FIXME: Set the PointBuffer's Bounds

    buffer.setSpatialBounds(block.GetBounds());
    m_currentBlockId++;
    return numPointsThisBlock;

}

bool ChipperSequentialIterator::atEndImpl() const
{
    // we don't have a fixed point point --
    // we are at the end only when our source is at the end
    const SequentialIterator& iter = getPrevIterator();
    return iter.atEnd();
}

// boost::uint64_t ChipperSequentialIterator::skipImpl(boost::uint64_t count)
// {
//     getPrevIterator().skip(count);
//     return count;
// }
//
//
// bool ChipperSequentialIterator::atEndImpl() const
// {
//     return getPrevIterator().atEnd();
// }
//
//
// boost::uint32_t ChipperSequentialIterator::readImpl(PointBuffer& data)
// {
//     const boost::uint32_t numRead = getPrevIterator().read(data);
//     // const boost::uint32_t cacheBlockSize = m_filter.getCacheBlockSize();
//     //
//     // const boost::uint64_t currentPointIndex = getIndex();
//     //
//     // // for now, we only read from the cache if they are asking for one point
//     // // (this avoids the problem of an N-point request needing more than one
//     // // cached block to satisfy it)
//     // if (data.getCapacity() != 1)
//     // {
//     //     const boost::uint32_t numRead = getPrevIterator().read(data);
//     //
//     //     // if they asked for a full block and we got a full block,
//     //     // and the block we got is properly aligned and not already cached,
//     //     // then let's cache it!
//     //     const bool isCacheable = (data.getCapacity() == cacheBlockSize) &&
//     //                              (numRead == cacheBlockSize) &&
//     //                              (currentPointIndex % cacheBlockSize == 0);
//     //     if (isCacheable && (m_filter.lookupInCache(currentPointIndex) == NULL))
//     //     {
//     //         m_filter.addToCache(currentPointIndex, data);
//     //     }
//     //
//     //     m_filter.updateStats(numRead, data.getCapacity());
//     //
//     //     return numRead;
//     // }
//     //
//     // // they asked for just one point -- first, check Mister Cache
//     // const PointBuffer* block = m_filter.lookupInCache(currentPointIndex);
//     // if (block != NULL)
//     // {
//     //     // A hit! A palpable hit!
//     //     data.copyPointFast(0,  currentPointIndex % cacheBlockSize, *block);
//     //
//     //     m_filter.updateStats(0, 1);
//     //
//     //     return 1;
//     // }
//     //
//     // // Not in the cache, so do a normal read :-(
//     // const boost::uint32_t numRead = getPrevIterator().read(data);
//     // m_filter.updateStats(numRead, numRead);
//
//     return numRead;
// }
//

} } // namespaces
<commit_msg>hop out of readImpl before resetting the buffer's count to 0<commit_after>/******************************************************************************
* Copyright (c) 2011, Michael P. Gerlek (mpg@flaxen.com)
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following
* conditions are met:
*
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in
*       the documentation and/or other materials provided
*       with the distribution.
*     * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the
*       names of its contributors may be used to endorse or promote
*       products derived from this software without specific prior
*       written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
****************************************************************************/

#include <libpc/filters/ChipperIterator.hpp>

namespace libpc { namespace filters {

ChipperSequentialIterator::ChipperSequentialIterator(Chipper const& filter)
    : libpc::FilterSequentialIterator(filter)
    , m_chipper(filter)
    , m_currentBlockId(0)
    , m_currentPointCount(0)
{
    const_cast<Chipper&>(m_chipper).Chip();
    return;
}

boost::uint64_t ChipperSequentialIterator::skipImpl(boost::uint64_t count)
{
    return naiveSkipImpl(count);
}

boost::uint32_t ChipperSequentialIterator::readImpl(PointBuffer& buffer)
{
    // The client has asked us for dstData.getCapacity() points.
    // We will read from our previous stage until we get that amount (or
    // until the previous stage runs out of points).

    if (m_currentBlockId == m_chipper.GetBlockCount())
        return 0; // we're done.

    buffer.setNumPoints(0);

    filters::chipper::Block const& block = m_chipper.GetBlock(m_currentBlockId);
    std::size_t numPointsThisBlock = block.GetIDs().size();
    m_currentPointCount = m_currentPointCount + numPointsThisBlock;

    if (buffer.getCapacity() < numPointsThisBlock)
    {
        // FIXME: Expand the buffer?
        throw libpc_error("Buffer not large enough to hold block!");
    }
    block.GetBuffer(m_chipper.getPrevStage(), buffer, m_currentBlockId);

    // FIXME: Set the PointBuffer's Bounds

    buffer.setSpatialBounds(block.GetBounds());
    m_currentBlockId++;
    return numPointsThisBlock;

}

bool ChipperSequentialIterator::atEndImpl() const
{
    // we don't have a fixed point point --
    // we are at the end only when our source is at the end
    const SequentialIterator& iter = getPrevIterator();
    return iter.atEnd();
}

// boost::uint64_t ChipperSequentialIterator::skipImpl(boost::uint64_t count)
// {
//     getPrevIterator().skip(count);
//     return count;
// }
//
//
// bool ChipperSequentialIterator::atEndImpl() const
// {
//     return getPrevIterator().atEnd();
// }
//
//
// boost::uint32_t ChipperSequentialIterator::readImpl(PointBuffer& data)
// {
//     const boost::uint32_t numRead = getPrevIterator().read(data);
//     // const boost::uint32_t cacheBlockSize = m_filter.getCacheBlockSize();
//     //
//     // const boost::uint64_t currentPointIndex = getIndex();
//     //
//     // // for now, we only read from the cache if they are asking for one point
//     // // (this avoids the problem of an N-point request needing more than one
//     // // cached block to satisfy it)
//     // if (data.getCapacity() != 1)
//     // {
//     //     const boost::uint32_t numRead = getPrevIterator().read(data);
//     //
//     //     // if they asked for a full block and we got a full block,
//     //     // and the block we got is properly aligned and not already cached,
//     //     // then let's cache it!
//     //     const bool isCacheable = (data.getCapacity() == cacheBlockSize) &&
//     //                              (numRead == cacheBlockSize) &&
//     //                              (currentPointIndex % cacheBlockSize == 0);
//     //     if (isCacheable && (m_filter.lookupInCache(currentPointIndex) == NULL))
//     //     {
//     //         m_filter.addToCache(currentPointIndex, data);
//     //     }
//     //
//     //     m_filter.updateStats(numRead, data.getCapacity());
//     //
//     //     return numRead;
//     // }
//     //
//     // // they asked for just one point -- first, check Mister Cache
//     // const PointBuffer* block = m_filter.lookupInCache(currentPointIndex);
//     // if (block != NULL)
//     // {
//     //     // A hit! A palpable hit!
//     //     data.copyPointFast(0,  currentPointIndex % cacheBlockSize, *block);
//     //
//     //     m_filter.updateStats(0, 1);
//     //
//     //     return 1;
//     // }
//     //
//     // // Not in the cache, so do a normal read :-(
//     // const boost::uint32_t numRead = getPrevIterator().read(data);
//     // m_filter.updateStats(numRead, numRead);
//
//     return numRead;
// }
//

} } // namespaces
<|endoftext|>