<commit_before>// Copyright 2015 Red Blob Games <redblobgames@gmail.com>
// License: Apache v2.0 <http://www.apache.org/licenses/LICENSE-2.0.html>

#include "render.h"
#include <SDL2/SDL.h>

#include "gl.h"
#include "textures.h"

#include <iostream>
#include <vector>

void GLERRORS(const char* name) {
#ifndef __EMSCRIPTEN__
  while (true) {
    GLenum err = glGetError();
    if (err == GL_NO_ERROR) { break; }
    std::cerr << name << " glGetError returned " << err << std::endl;
  }
#endif
}

static void SDLFAIL(const char* name) {
  GLERRORS(name);
  std::cerr << name << " failed : " << SDL_GetError() << std::endl;
  exit(EXIT_FAILURE);
}

struct VertexBuffer {
  GLuint sid, did, iid; // static vertex, dynamic vertex, and index

  VertexBuffer();
  ~VertexBuffer();
};

struct ShaderProgram {
  GLuint id;

  GLint loc_u_camera_position;
  GLint loc_u_camera_scale;
  GLint loc_u_texture;
  GLint loc_a_corner;
  GLint loc_a_position;
  GLint loc_a_rotation;
  GLint loc_a_scale;

  ShaderProgram();
  ~ShaderProgram();
  void AttachShader(GLenum type, const GLchar* source);
};

struct AttributesStatic {
  float corner[2]; // location of corner relative to center
  float scale; // size of sprite, in world coordinates
};

struct AttributesDynamic {
  float position[2]; // location of center in world coordinates
  float rotation; // rotation in radians
};

struct RendererImpl {
  SDL_Window* window;
  SDL_GLContext context;
  GLuint texture_id;
  Textures textures;
  std::unique_ptr<VertexBuffer> vbo;
  std::unique_ptr<ShaderProgram> shader;

  RendererImpl(SDL_Window* window);
  ~RendererImpl();
};

Renderer::Renderer(SDL_Window* window): self(new RendererImpl(window)) {}
Renderer::~Renderer() {}

RendererImpl::RendererImpl(SDL_Window* window_): window(window_) {
  SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

  context = SDL_GL_CreateContext(window);
  if (context == nullptr) { SDLFAIL("SDL_GL_CreateContext"); }

  glClearColor(1.0, 1.0, 1.0, 1.0);
  glEnable(GL_BLEND);
  glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

  shader = std::unique_ptr<ShaderProgram>(new ShaderProgram);
  vbo = std::unique_ptr<VertexBuffer>(new VertexBuffer);

  auto surface = textures.GetSurface();
  if (surface == nullptr) { SDLFAIL("Loading red-blob.png"); }

  glGenTextures(1, &texture_id);
  glBindTexture(GL_TEXTURE_2D, texture_id);
  glTexImage2D(GL_TEXTURE_2D, 0,
               GL_RGBA,
               surface->w, surface->h,
               0,
               surface->format->BytesPerPixel == 1? GL_ALPHA
               : surface->format->BytesPerPixel == 3? GL_RGB
               : GL_RGBA /* TODO: check for other formats */,
               GL_UNSIGNED_BYTE,
               surface->pixels
               );
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

  SDL_FreeSurface(surface);

  GLERRORS("Texture load");
}

RendererImpl::~RendererImpl() {
  shader = nullptr;
  vbo = nullptr;
  SDL_GL_DeleteContext(context);
  GLERRORS("~RendererImpl");
}

void Renderer::HandleResize() {
  // This is the easiest way to handle resize but it'd be better not
  // to regenerate the texture
  SDL_Window* window = self->window;
  self = nullptr;
  self = std::unique_ptr<RendererImpl>(new RendererImpl(window));
}

extern float rotation;
namespace {
  static int FRAME = -1;

  const int SIDE = 100;
  const int NUM = SIDE * SIDE;

  std::vector<AttributesStatic> vertices_static;
  std::vector<AttributesDynamic> vertices_dynamic;
  std::vector<GLushort> indices;
  static const float corner_vertex[4][2] = { { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 } };
  static const GLushort corner_index[6] = { 0, 1, 2, 2, 1, 3 };

  void FillVertexData() {
    static float t = 0.0;
    t += 0.025;

    if (FRAME % 100 == 0) {
      vertices_static.resize(NUM * 4);
      for (int i = 0; i < NUM * 4; i++) {
        AttributesStatic& record = vertices_static[i];
        record.corner[0] = corner_vertex[i % 4][0];
        record.corner[1] = corner_vertex[i % 4][1];
        record.scale = 3.0/SIDE;
      }

      indices.resize(NUM * 6);
      for (int i = 0; i < NUM * 6; i++) {
        int j = i / 6;
        indices[i] = j * 4 + corner_index[i % 6];
      }
    }

    vertices_dynamic.resize(NUM * 4);
    for (int i = 0; i < NUM * 4; i++) {
      AttributesDynamic& record = vertices_dynamic[i];
      int j = i / 4;
      record.position[0] = -1.0 + (j % SIDE) * 2.0 / SIDE;
      record.position[1] = -1.0 + (j / SIDE) * 2.0 / SIDE;
      record.rotation = rotation + (j * 0.02) + t;
    }
  }
}

void Renderer::Render() {
  FRAME++;
  glClear(GL_COLOR_BUFFER_BIT);

  glUseProgram(self->shader->id);
  GLERRORS("useProgram");

  // The uniforms are data that will be the same for all records. The
  // attributes are data in each record.
  extern float camera[2];
  GLfloat u_camera_position[2] = { camera[0], camera[1] };
  glUniform2fv(self->shader->loc_u_camera_position, 1, u_camera_position);

  // Rescale from world coordinates to OpenGL coordinates. We can
  // either choose for the world coordinates to have Y increasing
  // downwards (by setting u_camera_scale[1] to be negative) or have Y
  // increasing upwards and flipping the textures (by telling the
  // texture shader to flip the Y coordinate).
  int sdl_window_width, sdl_window_height;
  SDL_GL_GetDrawableSize(self->window, &sdl_window_width, &sdl_window_height);
  float sdl_window_size = std::min(sdl_window_height, sdl_window_width);
  GLfloat u_camera_scale[2] = { sdl_window_size / sdl_window_width,
                                -sdl_window_size / sdl_window_height };
  glUniform2fv(self->shader->loc_u_camera_scale, 1, u_camera_scale);

  GLERRORS("glUniform2fv");

  // Textures have an id and also a register (0 in this
  // case). We have to bind register 0 to the texture id:
  glActiveTexture(GL_TEXTURE0);
  glBindTexture(GL_TEXTURE_2D, self->texture_id);
  // and then we have to tell the shader which register (0) to use:
  glUniform1i(self->shader->loc_u_texture, 0);
  // It might be ok to hard-code the register number inside the shader.

  // The data for the vertex shader will be in a vertex buffer
  // ("VBO"). I'm going to use a single vertex buffer for all the
  // parameters, and I'm going to fill it each frame.
  FillVertexData();

  if (FRAME % 100 == 0) {
    glBindBuffer(GL_ARRAY_BUFFER, self->vbo->sid);
    glBufferData(GL_ARRAY_BUFFER, sizeof(AttributesStatic) * vertices_static.size(), vertices_static.data(), GL_STREAM_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self->vbo->iid);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * indices.size(), indices.data(), GL_STREAM_DRAW);
  }

  glBindBuffer(GL_ARRAY_BUFFER, self->vbo->did);
  glBufferData(GL_ARRAY_BUFFER, sizeof(AttributesDynamic) * vertices_dynamic.size(), vertices_dynamic.data(), GL_STREAM_DRAW);

  // Tell the shader program where to find each of the input variables
  // ("attributes") in its vertex shader input. They're all coming
  // from the same vertex buffer, but they're different slices of that
  // data. The API is flexible enough to allow us to have a start
  // position and stride within the vertex buffer. This allows us to
  // bind the position and rotation inside the struct.
  glBindBuffer(GL_ARRAY_BUFFER, self->vbo->sid);
  glVertexAttribPointer(self->shader->loc_a_corner,
                        2, GL_FLOAT, GL_FALSE, sizeof(AttributesStatic),
                        reinterpret_cast<GLvoid*>(offsetof(AttributesStatic, corner)));
  glVertexAttribPointer(self->shader->loc_a_scale,
                        1, GL_FLOAT, GL_FALSE, sizeof(AttributesStatic),
                        reinterpret_cast<GLvoid*>(offsetof(AttributesStatic, scale)));

  glBindBuffer(GL_ARRAY_BUFFER, self->vbo->did);
  glVertexAttribPointer(self->shader->loc_a_position,
                        2, GL_FLOAT, GL_FALSE, sizeof(AttributesDynamic),
                        reinterpret_cast<GLvoid*>(offsetof(AttributesDynamic, position)));
  glVertexAttribPointer(self->shader->loc_a_rotation,
                        1, GL_FLOAT, GL_FALSE, sizeof(AttributesDynamic),
                        reinterpret_cast<GLvoid*>(offsetof(AttributesDynamic, rotation)));

  GLERRORS("glVertexAttribPointer");

  // Run the shader program. Enable the vertex attribs just while
  // running this program. Which ones are enabled is global state, and
  // we don't want to interfere with any other shader programs we want
  // to run elsewhere.
  glEnableVertexAttribArray(self->shader->loc_a_corner);
  glEnableVertexAttribArray(self->shader->loc_a_position);
  glEnableVertexAttribArray(self->shader->loc_a_rotation);
  glEnableVertexAttribArray(self->shader->loc_a_scale);
  glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_SHORT, 0);
  glDisableVertexAttribArray(self->shader->loc_a_scale);
  glDisableVertexAttribArray(self->shader->loc_a_rotation);
  glDisableVertexAttribArray(self->shader->loc_a_position);
  glDisableVertexAttribArray(self->shader->loc_a_corner);
  GLERRORS("draw arrays");

  // In double buffering, all the drawing was to a screen buffer that
  // will now be displayed with this command:
  SDL_GL_SwapWindow(self->window);
}

// Vertex buffer stores the data needed to run the shader program

VertexBuffer::VertexBuffer() {
  glGenBuffers(1, &sid);
  glGenBuffers(1, &did);
  glGenBuffers(1, &iid);
  GLERRORS("VertexBuffer()");
}

VertexBuffer::~VertexBuffer() {
  glDeleteBuffers(1, &iid);
  glDeleteBuffers(1, &did);
  glDeleteBuffers(1, &sid);
}

// Shader program for drawing sprites

GLchar vertex_shader[] =
  "uniform vec2 u_camera_position;\n"
  "uniform vec2 u_camera_scale;\n"
  "attribute vec2 a_corner;\n"
  "attribute vec2 a_position;\n"
  "attribute float a_rotation;\n"
  "attribute float a_scale;\n"
  "varying vec2 loc;\n"
  "\n"
  "void main() {\n"
  "  mat2 rot = mat2(cos(a_rotation), -sin(a_rotation), sin(a_rotation), cos(a_rotation));\n"
  "  vec2 local_coords = (a_corner - vec2(0.5,0.5)) * rot * a_scale;\n"
  "  vec2 world_coords = local_coords + a_position;\n"
  "  vec2 screen_coords = (world_coords - u_camera_position) * u_camera_scale;\n"
  "  gl_Position = vec4(screen_coords, 0.0, 1.0);\n"
  "  loc = a_corner;\n"
  "}\n";

GLchar fragment_shader[] =
#ifdef __EMSCRIPTEN__
  // NOTE(amitp): WebGL requires precision hints but OpenGL 2.1 disallows them
  "precision mediump float;\n"
  "\n"
#endif
  "uniform sampler2D u_texture;\n"
  "varying vec2 loc;\n"
  "void main() {\n"
  "  gl_FragColor = texture2D(u_texture, loc);\n"
  "}\n";

ShaderProgram::ShaderProgram() {
  id = glCreateProgram();
  if (id == 0) { SDLFAIL("glCreateProgram"); }

  AttachShader(GL_VERTEX_SHADER, vertex_shader);
  AttachShader(GL_FRAGMENT_SHADER, fragment_shader);
  glLinkProgram(id);

  GLint link_status;
  glGetProgramiv(id, GL_LINK_STATUS, &link_status);
  if (!link_status) {
    GLint log_length;
    glGetProgramiv(id, GL_INFO_LOG_LENGTH, &log_length);
    GLchar log[1024];
    glGetProgramInfoLog(id, 1024, nullptr, log);
    std::cerr << log << std::endl;
    SDLFAIL("link shaders");
  }

  loc_u_camera_position = glGetUniformLocation(id, "u_camera_position");
  loc_u_camera_scale = glGetUniformLocation(id, "u_camera_scale");
  loc_u_texture = glGetUniformLocation(id, "u_texture");
  loc_a_corner = glGetAttribLocation(id, "a_corner");
  loc_a_position = glGetAttribLocation(id, "a_position");
  loc_a_rotation = glGetAttribLocation(id, "a_rotation");
  loc_a_scale = glGetAttribLocation(id, "a_scale");
}

ShaderProgram::~ShaderProgram() {
  glDeleteProgram(id);
}

void ShaderProgram::AttachShader(GLenum type, const GLchar* source) {
  GLuint shader_id = glCreateShader(type);
  if (shader_id == 0) { SDLFAIL("load shader"); }

  glShaderSource(shader_id, 1, &source, nullptr);
  glCompileShader(shader_id);

  GLint compile_status;
  glGetShaderiv(shader_id, GL_COMPILE_STATUS, &compile_status);
  if (!compile_status) {
    GLint log_length;
    glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH, &log_length);
    GLchar log[1024];
    glGetShaderInfoLog(shader_id, 1024, nullptr, log);
    std::cerr << log << std::endl;
    SDLFAIL("compile shader");
  }

  glAttachShader(id, shader_id);
  glDeleteShader(shader_id);
  GLERRORS("AttachShader()");
}
<commit_msg>Bug fix: reload GL buffers after a resize<commit_after>// Copyright 2015 Red Blob Games <redblobgames@gmail.com>
// License: Apache v2.0 <http://www.apache.org/licenses/LICENSE-2.0.html>

#include "render.h"
#include <SDL2/SDL.h>

#include "gl.h"
#include "textures.h"

#include <iostream>
#include <vector>

void GLERRORS(const char* name) {
#ifndef __EMSCRIPTEN__
  while (true) {
    GLenum err = glGetError();
    if (err == GL_NO_ERROR) { break; }
    std::cerr << name << " glGetError returned " << err << std::endl;
  }
#endif
}

static void SDLFAIL(const char* name) {
  GLERRORS(name);
  std::cerr << name << " failed : " << SDL_GetError() << std::endl;
  exit(EXIT_FAILURE);
}

struct VertexBuffer {
  GLuint sid, did, iid; // static vertex, dynamic vertex, and index

  VertexBuffer();
  ~VertexBuffer();
};

struct ShaderProgram {
  GLuint id;

  GLint loc_u_camera_position;
  GLint loc_u_camera_scale;
  GLint loc_u_texture;
  GLint loc_a_corner;
  GLint loc_a_position;
  GLint loc_a_rotation;
  GLint loc_a_scale;

  ShaderProgram();
  ~ShaderProgram();
  void AttachShader(GLenum type, const GLchar* source);
};

struct AttributesStatic {
  float corner[2]; // location of corner relative to center
  float scale; // size of sprite, in world coordinates
};

struct AttributesDynamic {
  float position[2]; // location of center in world coordinates
  float rotation; // rotation in radians
};

struct RendererImpl {
  bool context_initialized;
  SDL_Window* window;
  SDL_GLContext context;
  GLuint texture_id;
  Textures textures;
  std::unique_ptr<VertexBuffer> vbo;
  std::unique_ptr<ShaderProgram> shader;

  RendererImpl(SDL_Window* window);
  ~RendererImpl();
};

Renderer::Renderer(SDL_Window* window): self(new RendererImpl(window)) {}
Renderer::~Renderer() {}

RendererImpl::RendererImpl(SDL_Window* window_):
  context_initialized(false), window(window_)
{
  SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

  context = SDL_GL_CreateContext(window);
  if (context == nullptr) { SDLFAIL("SDL_GL_CreateContext"); }

  glClearColor(1.0, 1.0, 1.0, 1.0);
  glEnable(GL_BLEND);
  glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

  shader = std::unique_ptr<ShaderProgram>(new ShaderProgram);
  vbo = std::unique_ptr<VertexBuffer>(new VertexBuffer);

  auto surface = textures.GetSurface();
  if (surface == nullptr) { SDLFAIL("Loading red-blob.png"); }

  glGenTextures(1, &texture_id);
  glBindTexture(GL_TEXTURE_2D, texture_id);
  glTexImage2D(GL_TEXTURE_2D, 0,
               GL_RGBA,
               surface->w, surface->h,
               0,
               surface->format->BytesPerPixel == 1? GL_ALPHA
               : surface->format->BytesPerPixel == 3? GL_RGB
               : GL_RGBA /* TODO: check for other formats */,
               GL_UNSIGNED_BYTE,
               surface->pixels
               );
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

  SDL_FreeSurface(surface);

  GLERRORS("Texture load");
}

RendererImpl::~RendererImpl() {
  shader = nullptr;
  vbo = nullptr;
  SDL_GL_DeleteContext(context);
  GLERRORS("~RendererImpl");
}

void Renderer::HandleResize() {
  // This is the easiest way to handle resize but it'd be better not
  // to regenerate the texture.
  SDL_Window* window = self->window;
  self = nullptr;
  self = std::unique_ptr<RendererImpl>(new RendererImpl(window));
}

extern float rotation;
namespace {
  static int FRAME = -1;

  const int SIDE = 100;
  const int NUM = SIDE * SIDE;

  std::vector<AttributesStatic> vertices_static;
  std::vector<AttributesDynamic> vertices_dynamic;
  std::vector<GLushort> indices;
  static const float corner_vertex[4][2] = { { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 } };
  static const GLushort corner_index[6] = { 0, 1, 2, 2, 1, 3 };

  void FillVertexData() {
    static float t = 0.0;
    t += 0.025;

    if (FRAME % 100 == 0) {
      vertices_static.resize(NUM * 4);
      for (int i = 0; i < NUM * 4; i++) {
        AttributesStatic& record = vertices_static[i];
        record.corner[0] = corner_vertex[i % 4][0];
        record.corner[1] = corner_vertex[i % 4][1];
        record.scale = 3.0/SIDE;
      }

      indices.resize(NUM * 6);
      for (int i = 0; i < NUM * 6; i++) {
        int j = i / 6;
        indices[i] = j * 4 + corner_index[i % 6];
      }
    }

    vertices_dynamic.resize(NUM * 4);
    for (int i = 0; i < NUM * 4; i++) {
      AttributesDynamic& record = vertices_dynamic[i];
      int j = i / 4;
      record.position[0] = -1.0 + (j % SIDE) * 2.0 / SIDE;
      record.position[1] = -1.0 + (j / SIDE) * 2.0 / SIDE;
      record.rotation = rotation + (j * 0.02) + t;
    }
  }
}

void Renderer::Render() {
  FRAME++;
  glClear(GL_COLOR_BUFFER_BIT);

  glUseProgram(self->shader->id);
  GLERRORS("useProgram");

  // The uniforms are data that will be the same for all records. The
  // attributes are data in each record.
  extern float camera[2];
  GLfloat u_camera_position[2] = { camera[0], camera[1] };
  glUniform2fv(self->shader->loc_u_camera_position, 1, u_camera_position);

  // Rescale from world coordinates to OpenGL coordinates. We can
  // either choose for the world coordinates to have Y increasing
  // downwards (by setting u_camera_scale[1] to be negative) or have Y
  // increasing upwards and flipping the textures (by telling the
  // texture shader to flip the Y coordinate).
  int sdl_window_width, sdl_window_height;
  SDL_GL_GetDrawableSize(self->window, &sdl_window_width, &sdl_window_height);
  float sdl_window_size = std::min(sdl_window_height, sdl_window_width);
  GLfloat u_camera_scale[2] = { sdl_window_size / sdl_window_width,
                                -sdl_window_size / sdl_window_height };
  glUniform2fv(self->shader->loc_u_camera_scale, 1, u_camera_scale);

  GLERRORS("glUniform2fv");

  // Textures have an id and also a register (0 in this
  // case). We have to bind register 0 to the texture id:
  glActiveTexture(GL_TEXTURE0);
  glBindTexture(GL_TEXTURE_2D, self->texture_id);
  // and then we have to tell the shader which register (0) to use:
  glUniform1i(self->shader->loc_u_texture, 0);
  // It might be ok to hard-code the register number inside the shader.

  // The data for the vertex shader will be in a vertex buffer
  // ("VBO"). I'm going to use a single vertex buffer for all the
  // parameters, and I'm going to fill it each frame.
  FillVertexData();

  if (FRAME % 100 == 0 || !self->context_initialized) {
    glBindBuffer(GL_ARRAY_BUFFER, self->vbo->sid);
    glBufferData(GL_ARRAY_BUFFER, sizeof(AttributesStatic) * vertices_static.size(), vertices_static.data(), GL_DYNAMIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self->vbo->iid);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * indices.size(), indices.data(), GL_DYNAMIC_DRAW);
  }

  glBindBuffer(GL_ARRAY_BUFFER, self->vbo->did);
  glBufferData(GL_ARRAY_BUFFER, sizeof(AttributesDynamic) * vertices_dynamic.size(), vertices_dynamic.data(), GL_STREAM_DRAW);

  // Tell the shader program where to find each of the input variables
  // ("attributes") in its vertex shader input. They're all coming
  // from the same vertex buffer, but they're different slices of that
  // data. The API is flexible enough to allow us to have a start
  // position and stride within the vertex buffer. This allows us to
  // bind the position and rotation inside the struct.
  glBindBuffer(GL_ARRAY_BUFFER, self->vbo->sid);
  glVertexAttribPointer(self->shader->loc_a_corner,
                        2, GL_FLOAT, GL_FALSE, sizeof(AttributesStatic),
                        reinterpret_cast<GLvoid*>(offsetof(AttributesStatic, corner)));
  glVertexAttribPointer(self->shader->loc_a_scale,
                        1, GL_FLOAT, GL_FALSE, sizeof(AttributesStatic),
                        reinterpret_cast<GLvoid*>(offsetof(AttributesStatic, scale)));

  glBindBuffer(GL_ARRAY_BUFFER, self->vbo->did);
  glVertexAttribPointer(self->shader->loc_a_position,
                        2, GL_FLOAT, GL_FALSE, sizeof(AttributesDynamic),
                        reinterpret_cast<GLvoid*>(offsetof(AttributesDynamic, position)));
  glVertexAttribPointer(self->shader->loc_a_rotation,
                        1, GL_FLOAT, GL_FALSE, sizeof(AttributesDynamic),
                        reinterpret_cast<GLvoid*>(offsetof(AttributesDynamic, rotation)));

  GLERRORS("glVertexAttribPointer");

  self->context_initialized = true;

  // Run the shader program. Enable the vertex attribs just while
  // running this program. Which ones are enabled is global state, and
  // we don't want to interfere with any other shader programs we want
  // to run elsewhere.
  glEnableVertexAttribArray(self->shader->loc_a_corner);
  glEnableVertexAttribArray(self->shader->loc_a_position);
  glEnableVertexAttribArray(self->shader->loc_a_rotation);
  glEnableVertexAttribArray(self->shader->loc_a_scale);
  glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_SHORT, 0);
  glDisableVertexAttribArray(self->shader->loc_a_scale);
  glDisableVertexAttribArray(self->shader->loc_a_rotation);
  glDisableVertexAttribArray(self->shader->loc_a_position);
  glDisableVertexAttribArray(self->shader->loc_a_corner);
  GLERRORS("draw arrays");

  // In double buffering, all the drawing was to a screen buffer that
  // will now be displayed with this command:
  SDL_GL_SwapWindow(self->window);
}

// Vertex buffer stores the data needed to run the shader program

VertexBuffer::VertexBuffer() {
  glGenBuffers(1, &sid);
  glGenBuffers(1, &did);
  glGenBuffers(1, &iid);
  GLERRORS("VertexBuffer()");
}

VertexBuffer::~VertexBuffer() {
  glDeleteBuffers(1, &iid);
  glDeleteBuffers(1, &did);
  glDeleteBuffers(1, &sid);
}

// Shader program for drawing sprites

GLchar vertex_shader[] =
  "uniform vec2 u_camera_position;\n"
  "uniform vec2 u_camera_scale;\n"
  "attribute vec2 a_corner;\n"
  "attribute vec2 a_position;\n"
  "attribute float a_rotation;\n"
  "attribute float a_scale;\n"
  "varying vec2 loc;\n"
  "\n"
  "void main() {\n"
  "  mat2 rot = mat2(cos(a_rotation), -sin(a_rotation), sin(a_rotation), cos(a_rotation));\n"
  "  vec2 local_coords = (a_corner - vec2(0.5,0.5)) * rot * a_scale;\n"
  "  vec2 world_coords = local_coords + a_position;\n"
  "  vec2 screen_coords = (world_coords - u_camera_position) * u_camera_scale;\n"
  "  gl_Position = vec4(screen_coords, 0.0, 1.0);\n"
  "  loc = a_corner;\n"
  "}\n";

GLchar fragment_shader[] =
#ifdef __EMSCRIPTEN__
  // NOTE(amitp): WebGL requires precision hints but OpenGL 2.1 disallows them
  "precision mediump float;\n"
  "\n"
#endif
  "uniform sampler2D u_texture;\n"
  "varying vec2 loc;\n"
  "void main() {\n"
  "  gl_FragColor = texture2D(u_texture, loc);\n"
  "}\n";

ShaderProgram::ShaderProgram() {
  id = glCreateProgram();
  if (id == 0) { SDLFAIL("glCreateProgram"); }

  AttachShader(GL_VERTEX_SHADER, vertex_shader);
  AttachShader(GL_FRAGMENT_SHADER, fragment_shader);
  glLinkProgram(id);

  GLint link_status;
  glGetProgramiv(id, GL_LINK_STATUS, &link_status);
  if (!link_status) {
    GLint log_length;
    glGetProgramiv(id, GL_INFO_LOG_LENGTH, &log_length);
    GLchar log[1024];
    glGetProgramInfoLog(id, 1024, nullptr, log);
    std::cerr << log << std::endl;
    SDLFAIL("link shaders");
  }

  loc_u_camera_position = glGetUniformLocation(id, "u_camera_position");
  loc_u_camera_scale = glGetUniformLocation(id, "u_camera_scale");
  loc_u_texture = glGetUniformLocation(id, "u_texture");
  loc_a_corner = glGetAttribLocation(id, "a_corner");
  loc_a_position = glGetAttribLocation(id, "a_position");
  loc_a_rotation = glGetAttribLocation(id, "a_rotation");
  loc_a_scale = glGetAttribLocation(id, "a_scale");
}

ShaderProgram::~ShaderProgram() {
  glDeleteProgram(id);
}

void ShaderProgram::AttachShader(GLenum type, const GLchar* source) {
  GLuint shader_id = glCreateShader(type);
  if (shader_id == 0) { SDLFAIL("load shader"); }

  glShaderSource(shader_id, 1, &source, nullptr);
  glCompileShader(shader_id);

  GLint compile_status;
  glGetShaderiv(shader_id, GL_COMPILE_STATUS, &compile_status);
  if (!compile_status) {
    GLint log_length;
    glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH, &log_length);
    GLchar log[1024];
    glGetShaderInfoLog(shader_id, 1024, nullptr, log);
    std::cerr << log << std::endl;
    SDLFAIL("compile shader");
  }

  glAttachShader(id, shader_id);
  glDeleteShader(shader_id);
  GLERRORS("AttachShader()");
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include <QScopedPointer>
#include <QLatin1String>
#include <QGraphicsObject>
#include <QGuiApplication>
#include <QSettings>
#include <QFileInfo>
#include <QStringList>

#include <qmljs/qmljsimportdependencies.h>
#include <qmljs/qmljsinterpreter.h>
#include <qmljs/qmljsdocument.h>
#include <qmljs/qmljsbind.h>
#include <qmljs/qmljslink.h>
#include <qmljs/qmljscheck.h>
#include <qmljs/qmljscontext.h>
#include <qmljs/qmljsmodelmanagerinterface.h>
#include <utils/logging.h>

#include <QtTest>
#include <algorithm>

using namespace QmlJS;
using namespace QmlJS::AST;
using namespace QmlJS::StaticAnalysis;

class tst_ImportCheck : public QObject
{
    Q_OBJECT
public:
    tst_ImportCheck();

private slots:
    void test();
    void test_data();

    void initTestCase();
private:
    QStringList m_basePaths;
};

void scanDir(const QString &dir)
{
    QFutureInterface<void> result;
    PathsAndLanguages paths;
    paths.maybeInsert(Utils::FileName::fromString(dir), Dialect::Qml);
    ModelManagerInterface::importScan(result, ModelManagerInterface::workingCopy(), paths,
                                      ModelManagerInterface::instance(), false);
    ViewerContext vCtx = ViewerContext(QStringList(), QStringList(dir));
    Snapshot snap = ModelManagerInterface::instance()->snapshot();

    ImportDependencies *iDeps = snap.importDependencies();
    qDebug() << "libs:";
    foreach (const ImportKey &importK, iDeps->libraryImports(vCtx))
        qDebug() << "libImport: " << importK.toString();
    qDebug() << "qml files:";
    foreach (const ImportKey &importK, iDeps->subdirImports(ImportKey(ImportType::Directory, dir),
                                                           vCtx))
        qDebug() << importK.toString();
}

tst_ImportCheck::tst_ImportCheck()
{
}

#ifdef Q_OS_MAC
#  define SHARE_PATH "/Resources"
#else
#  define SHARE_PATH "/share/qtcreator"
#endif

QString resourcePath()
{
    return QDir::cleanPath(QTCREATORDIR + QLatin1String(SHARE_PATH));
}

void tst_ImportCheck::initTestCase()
{
    QLoggingCategory::setFilterRules(QLatin1String("qtc.*.debug=false"));
    if (!ModelManagerInterface::instance())
        new ModelManagerInterface;

    // the resource path is wrong, have to load things manually
    QFileInfo builtins(QString::fromLocal8Bit(TESTSRCDIR) + QLatin1String("/base"));
    if (builtins.exists())
        m_basePaths.append(builtins.filePath());
}

#define QCOMPARE_NOEXIT(actual, expected) \
    QTest::qCompare(actual, expected, #actual, #expected, __FILE__, __LINE__)

void tst_ImportCheck::test_data()
{
    QTest::addColumn<QStringList>("paths");
    QTest::addColumn<QStringList>("expectedLibraries");
    QTest::addColumn<QStringList>("expectedFiles");
    QTest::newRow("base") << QStringList(QLatin1String(TESTSRCDIR "/base"))
                          << (QStringList() << QLatin1String("QML 1.0")
                              << QLatin1String("QtQml 2.2")
                              << QLatin1String("QtQml 2.1")
                              << QLatin1String("QtQuick 2.0")
                              << QLatin1String("QtQml 2.0")
                              << QLatin1String("QtQuick 2.-1")
                              << QLatin1String("QtQuick 2.1")
                              << QLatin1String("QtQuick 2.2")
                              << QLatin1String("<cpp>"))
                          << QStringList();
    QTest::newRow("001_flatQmlOnly") << QStringList(QLatin1String(TESTSRCDIR "/001_flatQmlOnly"))
                          << QStringList()
                          << QStringList();
    QTest::newRow("002_nestedQmlOnly") << QStringList(QLatin1String(TESTSRCDIR "/002_nestedQmlOnly"))
                          << QStringList()
                          << QStringList();
    /*QTest::newRow("003_packageQmlOnly") << QStringList(QLatin1String(TESTSRCDIR "/003_packageQmlOnly"))
                          << (QStringList() << QLatin1String("QtGraphicalEffects"))
                          << (QStringList()
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/ZoomBlur.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/FastGlow.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/GaussianInnerShadow.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/SourceProxy.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/GammaAdjust.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/HueSaturation.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/Colorize.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/RadialBlur.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/ColorOverlay.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/MaskedBlur.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/RectangularGlow.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/Displace.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/FastMaskedBlur.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/Desaturate.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/GaussianDirectionalBlur.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/GaussianBlur.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/InnerShadow.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/LinearGradient.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/Blend.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/Glow.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/RecursiveBlur.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/GaussianMaskedBlur.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/DropShadow.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/DirectionalBlur.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/OpacityMask.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/BrightnessContrast.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/GaussianGlow.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/RadialGradient.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/FastInnerShadow.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/ConicalGradient.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/ThresholdMask.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/LevelAdjust.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/FastBlur.qml"));
    QTest::newRow("004_cppOnly copy") << QStringList(QLatin1String(TESTSRCDIR "004_cppOnly copy"))
                          << (QStringList() << QLatin1String("QML 1.0")
                              << QLatin1String("QtQml 2.2")
                              << QLatin1String("QtQml 2.1")
                              << QLatin1String("QtQuick 2.0")
                              << QLatin1String("QtQml 2.0")
                              << QLatin1String("QtQuick 2.-1")
                              << QLatin1String("QtQuick 2.1")
                              << QLatin1String("QtQuick 2.2")
                              << QLatin1String("<cpp>"))
                          << QStringList();*/
}

void tst_ImportCheck::test()
{
    QFETCH(QStringList, paths);
    QFETCH(QStringList, expectedLibraries);
    QFETCH(QStringList, expectedFiles);

    QFutureInterface<void> result;
    PathsAndLanguages lPaths;
    foreach (const QString &path, paths)
        lPaths.maybeInsert(Utils::FileName::fromString(path), Dialect::Qml);
    ModelManagerInterface::importScan(result, ModelManagerInterface::workingCopy(), lPaths,
                                      ModelManagerInterface::instance(), false);
    ViewerContext vCtx(QStringList(), paths);
    Snapshot snap = ModelManagerInterface::instance()->snapshot();

    ImportDependencies *iDeps = snap.importDependencies();
    QStringList detectedLibraries;
    QStringList detectedFiles;
    foreach (const ImportKey &importK, iDeps->libraryImports(vCtx))
        detectedLibraries << importK.toString();
    foreach (const QString &path, paths)
        foreach (const ImportKey &importK, iDeps->subdirImports(ImportKey(ImportType::Directory,
                                                                          path), vCtx))
        detectedFiles << QFileInfo(importK.toString()).canonicalFilePath();

    expectedLibraries.sort();
    expectedFiles.sort();
    detectedLibraries.sort();
    detectedFiles.sort();
    QCOMPARE(expectedLibraries, detectedLibraries);
    QCOMPARE(expectedFiles, detectedFiles);
}

#ifdef MANUAL_IMPORT_SCANNER

int main(int argc, char *argv[])
{
    QGuiApplication a(argc, argv);
    new ModelManagerInterface;
    if (argc != 2 || !QFileInfo(QString::fromLocal8Bit(argv[1])).isDir()) {
        printf("usage: %s dir/to/scan\n", ((argc > 0) ? argv[0] : "importScan"));
        exit(1);
    }
    tst_ImportCheck checker;
    QTimer::singleShot(1, &checker, SLOT(doScan()));
    a.exec();
    return 0;
}

#else

QTEST_MAIN(tst_ImportCheck)

#endif // MANUAL_IMPORT_SCANNER

#include "tst_importscheck.moc"
<commit_msg>Fix tests build<commit_after>/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include <QFileInfo>
#include <QGraphicsObject>
#include <QGuiApplication>
#include <QLatin1String>
#include <QLoggingCategory>
#include <QScopedPointer>
#include <QSettings>
#include <QStringList>
#include <QtTest>

#include <qmljs/qmljsbind.h>
#include <qmljs/qmljscheck.h>
#include <qmljs/qmljscontext.h>
#include <qmljs/qmljsdocument.h>
#include <qmljs/qmljsimportdependencies.h>
#include <qmljs/qmljsinterpreter.h>
#include <qmljs/qmljslink.h>
#include <qmljs/qmljsmodelmanagerinterface.h>

#include <algorithm>

using namespace QmlJS;
using namespace QmlJS::AST;
using namespace QmlJS::StaticAnalysis;

class tst_ImportCheck : public QObject
{
    Q_OBJECT
public:
    tst_ImportCheck();

private slots:
    void test();
    void test_data();

    void initTestCase();
private:
    QStringList m_basePaths;
};

void scanDir(const QString &dir)
{
    QFutureInterface<void> result;
    PathsAndLanguages paths;
    paths.maybeInsert(Utils::FileName::fromString(dir), Dialect::Qml);
    ModelManagerInterface::importScan(result, ModelManagerInterface::workingCopy(), paths,
                                      ModelManagerInterface::instance(), false);
    ViewerContext vCtx = ViewerContext(QStringList(), QStringList(dir));
    Snapshot snap = ModelManagerInterface::instance()->snapshot();

    ImportDependencies *iDeps = snap.importDependencies();
    qDebug() << "libs:";
    foreach (const ImportKey &importK, iDeps->libraryImports(vCtx))
        qDebug() << "libImport: " << importK.toString();
    qDebug() << "qml files:";
    foreach (const ImportKey &importK, iDeps->subdirImports(ImportKey(ImportType::Directory, dir),
                                                           vCtx))
        qDebug() << importK.toString();
}

tst_ImportCheck::tst_ImportCheck()
{
}

#ifdef Q_OS_MAC
#  define SHARE_PATH "/Resources"
#else
#  define SHARE_PATH "/share/qtcreator"
#endif

QString resourcePath()
{
    return QDir::cleanPath(QTCREATORDIR + QLatin1String(SHARE_PATH));
}

void tst_ImportCheck::initTestCase()
{
    QLoggingCategory::setFilterRules(QLatin1String("qtc.*.debug=false"));
    if (!ModelManagerInterface::instance())
        new ModelManagerInterface;

    // the resource path is wrong, have to load things manually
    QFileInfo builtins(QString::fromLocal8Bit(TESTSRCDIR) + QLatin1String("/base"));
    if (builtins.exists())
        m_basePaths.append(builtins.filePath());
}

#define QCOMPARE_NOEXIT(actual, expected) \
    QTest::qCompare(actual, expected, #actual, #expected, __FILE__, __LINE__)

void tst_ImportCheck::test_data()
{
    QTest::addColumn<QStringList>("paths");
    QTest::addColumn<QStringList>("expectedLibraries");
    QTest::addColumn<QStringList>("expectedFiles");
    QTest::newRow("base") << QStringList(QLatin1String(TESTSRCDIR "/base"))
                          << (QStringList() << QLatin1String("QML 1.0")
                              << QLatin1String("QtQml 2.2")
                              << QLatin1String("QtQml 2.1")
                              << QLatin1String("QtQuick 2.0")
                              << QLatin1String("QtQml 2.0")
                              << QLatin1String("QtQuick 2.-1")
                              << QLatin1String("QtQuick 2.1")
                              << QLatin1String("QtQuick 2.2")
                              << QLatin1String("<cpp>"))
                          << QStringList();
    QTest::newRow("001_flatQmlOnly") << QStringList(QLatin1String(TESTSRCDIR "/001_flatQmlOnly"))
                          << QStringList()
                          << QStringList();
    QTest::newRow("002_nestedQmlOnly") << QStringList(QLatin1String(TESTSRCDIR "/002_nestedQmlOnly"))
                          << QStringList()
                          << QStringList();
    /*QTest::newRow("003_packageQmlOnly") << QStringList(QLatin1String(TESTSRCDIR "/003_packageQmlOnly"))
                          << (QStringList() << QLatin1String("QtGraphicalEffects"))
                          << (QStringList()
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/ZoomBlur.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/FastGlow.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/GaussianInnerShadow.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/SourceProxy.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/GammaAdjust.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/HueSaturation.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/Colorize.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/RadialBlur.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/ColorOverlay.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/MaskedBlur.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/RectangularGlow.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/Displace.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/FastMaskedBlur.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/Desaturate.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/GaussianDirectionalBlur.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/GaussianBlur.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/InnerShadow.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/LinearGradient.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/Blend.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/Glow.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/RecursiveBlur.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/GaussianMaskedBlur.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/DropShadow.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/DirectionalBlur.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/OpacityMask.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/BrightnessContrast.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/GaussianGlow.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/RadialGradient.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/FastInnerShadow.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/ConicalGradient.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/ThresholdMask.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/LevelAdjust.qml")
                              << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/FastBlur.qml"));
    QTest::newRow("004_cppOnly copy") << QStringList(QLatin1String(TESTSRCDIR "004_cppOnly copy"))
                          << (QStringList() << QLatin1String("QML 1.0")
                              << QLatin1String("QtQml 2.2")
                              << QLatin1String("QtQml 2.1")
                              << QLatin1String("QtQuick 2.0")
                              << QLatin1String("QtQml 2.0")
                              << QLatin1String("QtQuick 2.-1")
                              << QLatin1String("QtQuick 2.1")
                              << QLatin1String("QtQuick 2.2")
                              << QLatin1String("<cpp>"))
                          << QStringList();*/
}

void tst_ImportCheck::test()
{
    QFETCH(QStringList, paths);
    QFETCH(QStringList, expectedLibraries);
    QFETCH(QStringList, expectedFiles);

    QFutureInterface<void> result;
    PathsAndLanguages lPaths;
    foreach (const QString &path, paths)
        lPaths.maybeInsert(Utils::FileName::fromString(path), Dialect::Qml);
    ModelManagerInterface::importScan(result, ModelManagerInterface::workingCopy(), lPaths,
                                      ModelManagerInterface::instance(), false);
    ViewerContext vCtx(QStringList(), paths);
    Snapshot snap = ModelManagerInterface::instance()->snapshot();

    ImportDependencies *iDeps = snap.importDependencies();
    QStringList detectedLibraries;
    QStringList detectedFiles;
    foreach (const ImportKey &importK, iDeps->libraryImports(vCtx))
        detectedLibraries << importK.toString();
    foreach (const QString &path, paths)
        foreach (const ImportKey &importK, iDeps->subdirImports(ImportKey(ImportType::Directory,
                                                                          path), vCtx))
        detectedFiles << QFileInfo(importK.toString()).canonicalFilePath();

    expectedLibraries.sort();
    expectedFiles.sort();
    detectedLibraries.sort();
    detectedFiles.sort();
    QCOMPARE(expectedLibraries, detectedLibraries);
    QCOMPARE(expectedFiles, detectedFiles);
}

#ifdef MANUAL_IMPORT_SCANNER

int main(int argc, char *argv[])
{
    QGuiApplication a(argc, argv);
    new ModelManagerInterface;
    if (argc != 2 || !QFileInfo(QString::fromLocal8Bit(argv[1])).isDir()) {
        printf("usage: %s dir/to/scan\n", ((argc > 0) ? argv[0] : "importScan"));
        exit(1);
    }
    tst_ImportCheck checker;
    QTimer::singleShot(1, &checker, SLOT(doScan()));
    a.exec();
    return 0;
}

#else

QTEST_MAIN(tst_ImportCheck)

#endif // MANUAL_IMPORT_SCANNER

#include "tst_importscheck.moc"
<|endoftext|>


<commit_before>/** Copyright (C) 2016, 2017 European Spallation Source ERIC */

#include <cinttypes>
#include <common/FBSerializer.h>
#include <common/Trace.h>
#include <common/DataSave.h>
#include <libs/include/gccintel.h>

#define TIMESIZE 4
#define PIXELSIZE 4

//#undef TRC_LEVEL
//#define TRC_LEVEL TRC_L_DEB

static_assert(FLATBUFFERS_LITTLEENDIAN,
              "Flatbuffers only tested on little endian systems");

FBSerializer::FBSerializer(size_t maxarraylength, Producer &prod)
    : builder(maxarraylength * 8 + 256), maxlen(maxarraylength),
      producer(prod) {

  auto sourceName = builder.CreateString("c_spec_data");
  std::uint64_t sequenceNr = 1; // Placeholder, must not be 0
  std::uint64_t pulseTime = 1;  // Placeholder, must not be 0
  auto timeoff = builder.CreateUninitializedVector(maxlen, TIMESIZE, &timeptr);
  auto pixeloff =
      builder.CreateUninitializedVector(maxlen, PIXELSIZE, &pixelptr);

  auto evMsgHeader = CreateEventMessage(builder, sourceName, sequenceNr,
                                        pulseTime, timeoff, pixeloff);
  FinishEventMessageBuffer(builder, evMsgHeader);

  //Use reinterpret_cast
  fbBufferPointer = (char *)builder.GetBufferPointer();
  fbSize = builder.GetSize();
  assert(fbSize > 0);
  assert(fbBufferPointer != nullptr);

  eventMsg = const_cast<EventMessage *>(GetEventMessage(fbBufferPointer));
  timeLenPtr =
      reinterpret_cast<flatbuffers::uoffset_t *>(
          const_cast<std::uint8_t *>(eventMsg->time_of_flight()->Data())) -
      1;
  pixelLenPtr =
      reinterpret_cast<flatbuffers::uoffset_t *>(
          const_cast<std::uint8_t *>(eventMsg->detector_id()->Data())) -
      1;
}

FBSerializer::~FBSerializer() {}

int FBSerializer::serialize(uint64_t time, uint64_t seqno, size_t entries,
                            char **buffer) {
  if (entries > maxlen) {
    *buffer = 0;
    return 0;
  }
  eventMsg->mutate_pulse_time(time);
  eventMsg->mutate_message_id(seqno);
  *timeLenPtr = entries;
  *pixelLenPtr = entries;

  *buffer = fbBufferPointer;
  return fbSize;
}

int FBSerializer::produce() {
  int txlen = 0;
  if (events != 0) {
    // Debug
    // for (unsigned int i = 0; i < events; i++) {
    //   printf("(%d, %d) ", i, ((uint32_t *)pixelptr)[i]);
    // }
    // printf("\n");

    XTRACE(OUTPUT, DEB, "produce %zu events \n", events);
    char *txbuffer;
    txlen = serialize((uint64_t)0x01, seqno++, events, &txbuffer);
    assert(txlen > 0);
    XTRACE(OUTPUT, DEB, "Flatbuffer tx length %d\n", txlen);
    producer.produce(txbuffer, txlen);

#if 0
      DataSave eventfb("eventfb", txbuffer, txlen);
      sleep(3);
      exit(1);
#endif
    events = 0;
  }
  return txlen;
}

int FBSerializer::addevent(uint32_t time, uint32_t pixel) {
  XTRACE(OUTPUT, DEB, "Add event: %d %u\n", time, pixel);
  ((uint32_t *)timeptr)[events] = time;
  ((uint32_t *)pixelptr)[events] = pixel;
  events++;

  /** Produce when enough data has been accumulated */
  if (events >= maxlen) {
    return produce();
  }
  return 0;
}
<commit_msg>Fixed cast.<commit_after>/** Copyright (C) 2016, 2017 European Spallation Source ERIC */

#include <cinttypes>
#include <common/FBSerializer.h>
#include <common/Trace.h>
#include <common/DataSave.h>
#include <libs/include/gccintel.h>

#define TIMESIZE 4
#define PIXELSIZE 4

//#undef TRC_LEVEL
//#define TRC_LEVEL TRC_L_DEB

static_assert(FLATBUFFERS_LITTLEENDIAN,
              "Flatbuffers only tested on little endian systems");

FBSerializer::FBSerializer(size_t maxarraylength, Producer &prod)
    : builder(maxarraylength * 8 + 256), maxlen(maxarraylength),
      producer(prod) {

  auto sourceName = builder.CreateString("c_spec_data");
  std::uint64_t sequenceNr = 1; // Placeholder, must not be 0
  std::uint64_t pulseTime = 1;  // Placeholder, must not be 0
  auto timeoff = builder.CreateUninitializedVector(maxlen, TIMESIZE, &timeptr);
  auto pixeloff =
      builder.CreateUninitializedVector(maxlen, PIXELSIZE, &pixelptr);

  auto evMsgHeader = CreateEventMessage(builder, sourceName, sequenceNr,
                                        pulseTime, timeoff, pixeloff);
  FinishEventMessageBuffer(builder, evMsgHeader);

  //Use reinterpret_cast
  fbBufferPointer = reinterpret_cast<char*>(builder.GetBufferPointer());
  fbSize = builder.GetSize();
  assert(fbSize > 0);
  assert(fbBufferPointer != nullptr);

  eventMsg = const_cast<EventMessage *>(GetEventMessage(fbBufferPointer));
  timeLenPtr =
      reinterpret_cast<flatbuffers::uoffset_t *>(
          const_cast<std::uint8_t *>(eventMsg->time_of_flight()->Data())) -
      1;
  pixelLenPtr =
      reinterpret_cast<flatbuffers::uoffset_t *>(
          const_cast<std::uint8_t *>(eventMsg->detector_id()->Data())) -
      1;
}

FBSerializer::~FBSerializer() {}

int FBSerializer::serialize(uint64_t time, uint64_t seqno, size_t entries,
                            char **buffer) {
  if (entries > maxlen) {
    *buffer = 0;
    return 0;
  }
  eventMsg->mutate_pulse_time(time);
  eventMsg->mutate_message_id(seqno);
  *timeLenPtr = entries;
  *pixelLenPtr = entries;

  *buffer = fbBufferPointer;
  return fbSize;
}

int FBSerializer::produce() {
  int txlen = 0;
  if (events != 0) {
    // Debug
    // for (unsigned int i = 0; i < events; i++) {
    //   printf("(%d, %d) ", i, ((uint32_t *)pixelptr)[i]);
    // }
    // printf("\n");

    XTRACE(OUTPUT, DEB, "produce %zu events \n", events);
    char *txbuffer;
    txlen = serialize((uint64_t)0x01, seqno++, events, &txbuffer);
    assert(txlen > 0);
    XTRACE(OUTPUT, DEB, "Flatbuffer tx length %d\n", txlen);
    producer.produce(txbuffer, txlen);

#if 0
      DataSave eventfb("eventfb", txbuffer, txlen);
      sleep(3);
      exit(1);
#endif
    events = 0;
  }
  return txlen;
}

int FBSerializer::addevent(uint32_t time, uint32_t pixel) {
  XTRACE(OUTPUT, DEB, "Add event: %d %u\n", time, pixel);
  ((uint32_t *)timeptr)[events] = time;
  ((uint32_t *)pixelptr)[events] = pixel;
  events++;

  /** Produce when enough data has been accumulated */
  if (events >= maxlen) {
    return produce();
  }
  return 0;
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

#include "dll/base_conf.hpp"
#include "dll/contrastive_divergence.hpp"
#include "dll/watcher.hpp"
#include "dll/util/tmp.hpp"

namespace dll {

/*!
 * \brief Describe a dynamic Convolutional Restricted Boltzmann Machine.  *
 * This struct should be used to define a RBM either as standalone or for a DBN.
 * Once configured, the ::layer_t member returns the type of the configured RBM.
 */
template <typename... Parameters>
struct dyn_conv_rbm_desc {
    /*!
     * \brief A list of all the parameters of the descriptor
     */
    using parameters = cpp::type_list<Parameters...>;

    static constexpr const unit_type visible_unit   = detail::get_value<visible<unit_type::BINARY>, Parameters...>::value;
    static constexpr const unit_type hidden_unit    = detail::get_value<hidden<unit_type::BINARY>, Parameters...>::value;
    static constexpr const sparsity_method Sparsity = detail::get_value<sparsity<sparsity_method::NONE>, Parameters...>::value;
    static constexpr const bias_mode Bias           = detail::get_value<bias<bias_mode::SIMPLE>, Parameters...>::value;

    /*! The type used to store the weights */
    using weight = typename detail::get_type<weight_type<float>, Parameters...>::value;

    /*! The type of the trainer to use to train the RBM */
    template <typename RBM, bool Denoising>
    using trainer_t = typename detail::get_template_type_tb<trainer_rbm<cd1_trainer_t>, Parameters...>::template value<RBM, Denoising>;

    /*! The type of the watched to use during training */
    template <typename RBM>
    using watcher_t = typename detail::get_template_type<watcher<default_rbm_watcher>, Parameters...>::template value<RBM>;

    /*! The layer type */
    using layer_t = dyn_conv_rbm<dyn_conv_rbm_desc<Parameters...>>;

    /*! The layer type */
    using dyn_layer_t = dyn_conv_rbm<dyn_conv_rbm_desc<Parameters...>>;

    //Make sure only valid types are passed to the configuration list
    static_assert(
        detail::is_valid<cpp::type_list<
                             momentum_id, visible_id, hidden_id, dbn_only_id, memory_id, clip_gradients_id,
                             weight_decay_id, sparsity_id, trainer_rbm_id, watcher_id,
                             bias_id, weight_type_id, shuffle_id, parallel_mode_id, serial_id, verbose_id, nop_id>,
                         Parameters...>::value,
        "Invalid parameters type");

    static_assert(Sparsity == sparsity_method::NONE || hidden_unit == unit_type::BINARY,
                  "Sparsity only works with binary hidden units");
};

} //end of dll namespace
<commit_msg>Cleanup<commit_after>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

#include "dll/base_conf.hpp"
#include "dll/contrastive_divergence.hpp"
#include "dll/watcher.hpp"
#include "dll/util/tmp.hpp"

namespace dll {

/*!
 * \brief Describe a dynamic Convolutional Restricted Boltzmann Machine.  *
 * This struct should be used to define a RBM either as standalone or for a DBN.
 * Once configured, the ::layer_t member returns the type of the configured RBM.
 */
template <typename... Parameters>
struct dyn_conv_rbm_desc {
    /*!
     * \brief A list of all the parameters of the descriptor
     */
    using parameters = cpp::type_list<Parameters...>;

    static constexpr const unit_type visible_unit   = detail::get_value<visible<unit_type::BINARY>, Parameters...>::value;
    static constexpr const unit_type hidden_unit    = detail::get_value<hidden<unit_type::BINARY>, Parameters...>::value;
    static constexpr const sparsity_method Sparsity = detail::get_value<sparsity<sparsity_method::NONE>, Parameters...>::value;
    static constexpr const bias_mode Bias           = detail::get_value<bias<bias_mode::SIMPLE>, Parameters...>::value;

    /*! The type used to store the weights */
    using weight = typename detail::get_type<weight_type<float>, Parameters...>::value;

    /*! The type of the trainer to use to train the RBM */
    template <typename RBM, bool Denoising>
    using trainer_t = typename detail::get_template_type_tb<trainer_rbm<cd1_trainer_t>, Parameters...>::template value<RBM, Denoising>;

    /*! The type of the watched to use during training */
    template <typename RBM>
    using watcher_t = typename detail::get_template_type<watcher<default_rbm_watcher>, Parameters...>::template value<RBM>;

    /*! The layer type */
    using layer_t = dyn_conv_rbm<dyn_conv_rbm_desc<Parameters...>>;

    /*! The layer type */
    using dyn_layer_t = layer_t;

    //Make sure only valid types are passed to the configuration list
    static_assert(
        detail::is_valid<cpp::type_list<
                             momentum_id, visible_id, hidden_id, dbn_only_id, memory_id, clip_gradients_id,
                             weight_decay_id, sparsity_id, trainer_rbm_id, watcher_id,
                             bias_id, weight_type_id, shuffle_id, parallel_mode_id, serial_id, verbose_id, nop_id>,
                         Parameters...>::value,
        "Invalid parameters type");

    static_assert(Sparsity == sparsity_method::NONE || hidden_unit == unit_type::BINARY,
                  "Sparsity only works with binary hidden units");
};

} //end of dll namespace
<|endoftext|>


<commit_before>#ifndef NODE_BASED_EDGE_HPP
#define NODE_BASED_EDGE_HPP

#include <cstdint>
#include <tuple>

#include "extractor/class_data.hpp"
#include "extractor/travel_mode.hpp"
#include "util/typedefs.hpp"

#include "extractor/guidance/road_classification.hpp"

namespace osrm
{
namespace extractor
{

// Flags describing the class of the road. This data is used during creation of graphs/guidance
// generation but is not available in annotation/navigation
struct NodeBasedEdgeClassification
{
    std::uint8_t forward : 1;                         // 1
    std::uint8_t backward : 1;                        // 1
    std::uint8_t is_split : 1;                        // 1
    std::uint8_t roundabout : 1;                      // 1
    std::uint8_t circular : 1;                        // 1
    std::uint8_t startpoint : 1;                      // 1
    std::uint8_t restricted : 1;                      // 1
    guidance::RoadClassification road_classification; // 16 2

    NodeBasedEdgeClassification();

    NodeBasedEdgeClassification(const bool forward,
                                const bool backward,
                                const bool is_split,
                                const bool roundabout,
                                const bool circular,
                                const bool startpoint,
                                const bool restricted,
                                guidance::RoadClassification road_classification)
        : forward(forward), backward(backward), is_split(is_split), roundabout(roundabout),
          circular(circular), startpoint(startpoint), restricted(restricted),
          road_classification(road_classification)
    {
    }

    bool operator==(const NodeBasedEdgeClassification &other) const
    {
        return (road_classification == other.road_classification) && (forward == other.forward) &&
               (backward == other.backward) && (is_split) == (other.is_split) &&
               (roundabout == other.roundabout) && (circular == other.circular) &&
               (startpoint == other.startpoint) && (restricted == other.restricted);
    }
};

// Annotative data, used in parts in guidance generation, in parts during navigation (classes) but
// mostly for annotation of edges. The entry can be shared between multiple edges and usually
// describes features present on OSM ways. This is the place to put specific data that you want to
// see as part of the API output but that does not influence navigation
struct NodeBasedEdgeAnnotation
{
    NameID name_id;                        // 32 4
    LaneDescriptionID lane_description_id; // 16 2
    ClassData classes;                     // 8  1
    TravelMode travel_mode : 4;            // 4
    bool is_left_hand_driving : 1;         // 1

    bool CanCombineWith(const NodeBasedEdgeAnnotation &other) const
    {
        return (std::tie(name_id, classes, travel_mode, is_left_hand_driving) ==
                std::tie(other.name_id, other.classes, other.travel_mode, is_left_hand_driving));
    }
};

struct NodeBasedEdge
{
    NodeBasedEdge();

    NodeBasedEdge(NodeID source,
                  NodeID target,
                  EdgeWeight weight,
                  EdgeDuration duration,
                  GeometryID geometry_id,
                  AnnotationID annotation_data,
                  NodeBasedEdgeClassification flags);

    bool operator<(const NodeBasedEdge &other) const;

    NodeID source;                     // 32 4
    NodeID target;                     // 32 4
    EdgeWeight weight;                 // 32 4
    EdgeDuration duration;             // 32 4
    GeometryID geometry_id;            // 32 4
    AnnotationID annotation_data;      // 32 4
    NodeBasedEdgeClassification flags; // 32 4
};

struct NodeBasedEdgeWithOSM : NodeBasedEdge
{
    NodeBasedEdgeWithOSM();

    NodeBasedEdgeWithOSM(OSMNodeID source,
                         OSMNodeID target,
                         EdgeWeight weight,
                         EdgeDuration duration,
                         GeometryID geometry_id,
                         AnnotationID annotation_data,
                         NodeBasedEdgeClassification flags);

    OSMNodeID osm_source_id;
    OSMNodeID osm_target_id;
};

// Impl.

inline NodeBasedEdgeClassification::NodeBasedEdgeClassification()
    : forward(false), backward(false), is_split(false), roundabout(false), circular(false),
      startpoint(false), restricted(false)
{
}

inline NodeBasedEdge::NodeBasedEdge()
    : source(SPECIAL_NODEID), target(SPECIAL_NODEID), weight(0), duration(0), annotation_data(-1)
{
}

inline NodeBasedEdge::NodeBasedEdge(NodeID source,
                                    NodeID target,
                                    EdgeWeight weight,
                                    EdgeDuration duration,
                                    GeometryID geometry_id,
                                    AnnotationID annotation_data,
                                    NodeBasedEdgeClassification flags)
    : source(source), target(target), weight(weight), duration(duration), geometry_id(geometry_id),
      annotation_data(annotation_data), flags(flags)
{
}

inline bool NodeBasedEdge::operator<(const NodeBasedEdge &other) const
{
    if (source == other.source)
    {
        if (target == other.target)
        {
            if (weight == other.weight)
            {
                return flags.forward && flags.backward &&
                       ((!other.flags.forward) || (!other.flags.backward));
            }
            return weight < other.weight;
        }
        return target < other.target;
    }
    return source < other.source;
}

inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(OSMNodeID source,
                                                  OSMNodeID target,
                                                  EdgeWeight weight,
                                                  EdgeDuration duration,
                                                  GeometryID geometry_id,
                                                  AnnotationID annotation_data,
                                                  NodeBasedEdgeClassification flags)
    : NodeBasedEdge(
          SPECIAL_NODEID, SPECIAL_NODEID, weight, duration, geometry_id, annotation_data, flags),
      osm_source_id(std::move(source)), osm_target_id(std::move(target))
{
}

inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM()
    : osm_source_id(MIN_OSM_NODEID), osm_target_id(MIN_OSM_NODEID)
{
}

static_assert(sizeof(extractor::NodeBasedEdge) == 28,
              "Size of extractor::NodeBasedEdge type is "
              "bigger than expected. This will influence "
              "memory consumption.");

} // ns extractor
} // ns osrm

#endif /* NODE_BASED_EDGE_HPP */
<commit_msg>Fixed c/p typo.<commit_after>#ifndef NODE_BASED_EDGE_HPP
#define NODE_BASED_EDGE_HPP

#include <cstdint>
#include <tuple>

#include "extractor/class_data.hpp"
#include "extractor/travel_mode.hpp"
#include "util/typedefs.hpp"

#include "extractor/guidance/road_classification.hpp"

namespace osrm
{
namespace extractor
{

// Flags describing the class of the road. This data is used during creation of graphs/guidance
// generation but is not available in annotation/navigation
struct NodeBasedEdgeClassification
{
    std::uint8_t forward : 1;                         // 1
    std::uint8_t backward : 1;                        // 1
    std::uint8_t is_split : 1;                        // 1
    std::uint8_t roundabout : 1;                      // 1
    std::uint8_t circular : 1;                        // 1
    std::uint8_t startpoint : 1;                      // 1
    std::uint8_t restricted : 1;                      // 1
    guidance::RoadClassification road_classification; // 16 2

    NodeBasedEdgeClassification();

    NodeBasedEdgeClassification(const bool forward,
                                const bool backward,
                                const bool is_split,
                                const bool roundabout,
                                const bool circular,
                                const bool startpoint,
                                const bool restricted,
                                guidance::RoadClassification road_classification)
        : forward(forward), backward(backward), is_split(is_split), roundabout(roundabout),
          circular(circular), startpoint(startpoint), restricted(restricted),
          road_classification(road_classification)
    {
    }

    bool operator==(const NodeBasedEdgeClassification &other) const
    {
        return (road_classification == other.road_classification) && (forward == other.forward) &&
               (backward == other.backward) && (is_split) == (other.is_split) &&
               (roundabout == other.roundabout) && (circular == other.circular) &&
               (startpoint == other.startpoint) && (restricted == other.restricted);
    }
};

// Annotative data, used in parts in guidance generation, in parts during navigation (classes) but
// mostly for annotation of edges. The entry can be shared between multiple edges and usually
// describes features present on OSM ways. This is the place to put specific data that you want to
// see as part of the API output but that does not influence navigation
struct NodeBasedEdgeAnnotation
{
    NameID name_id;                        // 32 4
    LaneDescriptionID lane_description_id; // 16 2
    ClassData classes;                     // 8  1
    TravelMode travel_mode : 4;            // 4
    bool is_left_hand_driving : 1;         // 1

    bool CanCombineWith(const NodeBasedEdgeAnnotation &other) const
    {
        return (
            std::tie(name_id, classes, travel_mode, is_left_hand_driving) ==
            std::tie(other.name_id, other.classes, other.travel_mode, other.is_left_hand_driving));
    }
};

struct NodeBasedEdge
{
    NodeBasedEdge();

    NodeBasedEdge(NodeID source,
                  NodeID target,
                  EdgeWeight weight,
                  EdgeDuration duration,
                  GeometryID geometry_id,
                  AnnotationID annotation_data,
                  NodeBasedEdgeClassification flags);

    bool operator<(const NodeBasedEdge &other) const;

    NodeID source;                     // 32 4
    NodeID target;                     // 32 4
    EdgeWeight weight;                 // 32 4
    EdgeDuration duration;             // 32 4
    GeometryID geometry_id;            // 32 4
    AnnotationID annotation_data;      // 32 4
    NodeBasedEdgeClassification flags; // 32 4
};

struct NodeBasedEdgeWithOSM : NodeBasedEdge
{
    NodeBasedEdgeWithOSM();

    NodeBasedEdgeWithOSM(OSMNodeID source,
                         OSMNodeID target,
                         EdgeWeight weight,
                         EdgeDuration duration,
                         GeometryID geometry_id,
                         AnnotationID annotation_data,
                         NodeBasedEdgeClassification flags);

    OSMNodeID osm_source_id;
    OSMNodeID osm_target_id;
};

// Impl.

inline NodeBasedEdgeClassification::NodeBasedEdgeClassification()
    : forward(false), backward(false), is_split(false), roundabout(false), circular(false),
      startpoint(false), restricted(false)
{
}

inline NodeBasedEdge::NodeBasedEdge()
    : source(SPECIAL_NODEID), target(SPECIAL_NODEID), weight(0), duration(0), annotation_data(-1)
{
}

inline NodeBasedEdge::NodeBasedEdge(NodeID source,
                                    NodeID target,
                                    EdgeWeight weight,
                                    EdgeDuration duration,
                                    GeometryID geometry_id,
                                    AnnotationID annotation_data,
                                    NodeBasedEdgeClassification flags)
    : source(source), target(target), weight(weight), duration(duration), geometry_id(geometry_id),
      annotation_data(annotation_data), flags(flags)
{
}

inline bool NodeBasedEdge::operator<(const NodeBasedEdge &other) const
{
    if (source == other.source)
    {
        if (target == other.target)
        {
            if (weight == other.weight)
            {
                return flags.forward && flags.backward &&
                       ((!other.flags.forward) || (!other.flags.backward));
            }
            return weight < other.weight;
        }
        return target < other.target;
    }
    return source < other.source;
}

inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(OSMNodeID source,
                                                  OSMNodeID target,
                                                  EdgeWeight weight,
                                                  EdgeDuration duration,
                                                  GeometryID geometry_id,
                                                  AnnotationID annotation_data,
                                                  NodeBasedEdgeClassification flags)
    : NodeBasedEdge(
          SPECIAL_NODEID, SPECIAL_NODEID, weight, duration, geometry_id, annotation_data, flags),
      osm_source_id(std::move(source)), osm_target_id(std::move(target))
{
}

inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM()
    : osm_source_id(MIN_OSM_NODEID), osm_target_id(MIN_OSM_NODEID)
{
}

static_assert(sizeof(extractor::NodeBasedEdge) == 28,
              "Size of extractor::NodeBasedEdge type is "
              "bigger than expected. This will influence "
              "memory consumption.");

} // ns extractor
} // ns osrm

#endif /* NODE_BASED_EDGE_HPP */
<|endoftext|>


<commit_before>/*

Copyright (c) 2006, Arvid Norberg
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 the author 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.

*/

#ifndef TORRENT_SESSION_STATUS_HPP_INCLUDED
#define TORRENT_SESSION_STATUS_HPP_INCLUDED

namespace libtorrent
{

#ifndef TORRENT_DISABLE_DHT

	struct dht_lookup
	{
		char const* type;
		int outstanding_requests;
		int timeouts;
		int responses;
		int branch_factor;
	};

#endif

	struct TORRENT_EXPORT session_status
	{
		bool has_incoming_connections;

		float upload_rate;
		float download_rate;
		size_type total_download;
		size_type total_upload;

		float payload_upload_rate;
		float payload_download_rate;
		size_type total_payload_download;
		size_type total_payload_upload;

		float ip_overhead_upload_rate;
		float ip_overhead_download_rate;
		size_type total_ip_overhead_download;
		size_type total_ip_overhead_upload;

		float dht_upload_rate;
		float dht_download_rate;
		size_type total_dht_download;
		size_type total_dht_upload;

		float tracker_upload_rate;
		float tracker_download_rate;
		size_type total_tracker_download;
		size_type total_tracker_upload;

		size_type total_redundant_bytes;
		size_type total_failed_bytes;

		int num_peers;
		int num_unchoked;
		int allowed_upload_slots;

		int up_bandwidth_queue;
		int down_bandwidth_queue;

		int optimistic_unchoke_counter;
		int unchoke_counter;

#ifndef TORRENT_DISABLE_DHT
		int dht_nodes;
		int dht_node_cache;
		int dht_torrents;
		size_type dht_global_nodes;
		std::vector<dht_lookup> active_requests;
#endif
	};

}

#endif // TORRENT_SESSION_STATUS_HPP_INCLUDED

<commit_msg>fixed missing includes in header<commit_after>/*

Copyright (c) 2006, Arvid Norberg
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 the author 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.

*/

#ifndef TORRENT_SESSION_STATUS_HPP_INCLUDED
#define TORRENT_SESSION_STATUS_HPP_INCLUDED

#include "libtorrent/config.hpp"
#include "libtorrent/size_type.hpp"

namespace libtorrent
{

#ifndef TORRENT_DISABLE_DHT

	struct dht_lookup
	{
		char const* type;
		int outstanding_requests;
		int timeouts;
		int responses;
		int branch_factor;
	};

#endif

	struct TORRENT_EXPORT session_status
	{
		bool has_incoming_connections;

		float upload_rate;
		float download_rate;
		size_type total_download;
		size_type total_upload;

		float payload_upload_rate;
		float payload_download_rate;
		size_type total_payload_download;
		size_type total_payload_upload;

		float ip_overhead_upload_rate;
		float ip_overhead_download_rate;
		size_type total_ip_overhead_download;
		size_type total_ip_overhead_upload;

		float dht_upload_rate;
		float dht_download_rate;
		size_type total_dht_download;
		size_type total_dht_upload;

		float tracker_upload_rate;
		float tracker_download_rate;
		size_type total_tracker_download;
		size_type total_tracker_upload;

		size_type total_redundant_bytes;
		size_type total_failed_bytes;

		int num_peers;
		int num_unchoked;
		int allowed_upload_slots;

		int up_bandwidth_queue;
		int down_bandwidth_queue;

		int optimistic_unchoke_counter;
		int unchoke_counter;

#ifndef TORRENT_DISABLE_DHT
		int dht_nodes;
		int dht_node_cache;
		int dht_torrents;
		size_type dht_global_nodes;
		std::vector<dht_lookup> active_requests;
#endif
	};

}

#endif // TORRENT_SESSION_STATUS_HPP_INCLUDED

<|endoftext|>