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

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#include "sjpegi.h"

using namespace sjpeg;

////////////////////////////////////////////////////////////////////////////////
// dichotomy

#define DBG_PRINT 0

// convergence is considered reached if |dq| < kdQLimit.
static const float kdQLimit = 0.15;

static float Clamp(float v, float min, float max) {
  return (v < min) ? min : (v > max) ? max : v;
}

bool SearchHook::Setup(const SjpegEncodeParam& param) {
  for_size = (param.target_mode == SjpegEncodeParam::TARGET_SIZE);
  target = param.target_value;
  tolerance = param.tolerance / 100.;
  qmin = (param.qmin < 0) ? 0 : param.qmin;
  qmax = (param.qmax > 100) ? 100 :
         (param.qmax < param.qmin) ? param.qmin : param.qmax;
  q = Clamp(SjpegEstimateQuality(param.quant_[0], false), qmin, qmax);
  value = 0;   // undefined for at this point
  return true;
}

bool SearchHook::Update(float result) {
  value = result;
  bool done = (fabs(value - target) < tolerance * target);
  if (done) return true;

  if (value > target) {
    qmax = q;
  } else {
    qmin = q;
  }
  const float last_q = q;
  q = (qmin + qmax) / 2.;
  done = (fabs(q - last_q) < kdQLimit);
  if (DBG_PRINT) {
    printf("q=%.2f value:%.1f -> next-q=%.2f\n", last_q, value, q);
  }
  return done;
}

void SearchHook::NextMatrix(int idx, uint8_t dst[64]) {
  SetQuantMatrix(kDefaultMatrices[idx], GetQFactor(q), dst);
}

////////////////////////////////////////////////////////////////////////////////
// Helpers for the search

void Encoder::StoreRunLevels(DCTCoeffs* coeffs) {
  assert(use_extra_memory_);
  assert(reuse_run_levels_);

  const QuantizeBlockFunc quantize_block = use_trellis_ ? TrellisQuantizeBlock
                                                        : quantize_block_;
  if (use_trellis_) InitCodes(true);

  ResetDCs();
  nb_run_levels_ = 0;
  int16_t* in = in_blocks_;
  for (int n = 0; n < mb_w_ * mb_h_; ++n) {
    CheckBuffers();
    for (int c = 0; c < nb_comps_; ++c) {
      for (int i = 0; i < nb_blocks_[c]; ++i) {
        RunLevel* const run_levels = all_run_levels_ + nb_run_levels_;
        const int dc = quantize_block(in, c, &quants_[quant_idx_[c]],
                                      coeffs, run_levels);
        coeffs->dc_code_ = GenerateDCDiffCode(dc, &DCs_[c]);
        nb_run_levels_ += coeffs->nb_coeffs_;
        ++coeffs;
        in += 64;
      }
    }
  }
}

void Encoder::LoopScan() {
  assert(use_extra_memory_);
  assert(reuse_run_levels_);

  if (use_adaptive_quant_) {
    CollectHistograms();
  } else {
    CollectCoeffs();   // we just need the coeffs
  }

  const size_t nb_mbs = mb_w_ * mb_h_ * mcu_blocks_;
  DCTCoeffs* const base_coeffs = new DCTCoeffs[nb_mbs];

  uint8_t opt_quants[2][64];

  // Dichotomy passes
  float best = 0.;     // best distance
  float best_q = 0.;  // informative value to return to the user
  float best_result = 0.;
  for (int p = 0; p < passes_; ++p) {
    // set new matrices to evaluate
    for (int c = 0; c < 2; ++c) {
      search_hook_->NextMatrix(c, quants_[c].quant_);
      FinalizeQuantMatrix(&quants_[c], q_bias_);
    }
    if (use_adaptive_quant_) {
      AnalyseHisto();   // adjust quant_[] matrices
    }

    float result;
    if (search_hook_->for_size) {
      // compute pass to store coeffs / runs / dc_code_
      StoreRunLevels(base_coeffs);
      if (optimize_size_) {
        StoreOptimalHuffmanTables(nb_mbs, base_coeffs);
        if (use_trellis_) InitCodes(true);
      }
      result = ComputeSize(base_coeffs);
    } else {
      // if we're just targeting PSNR, we don't need to compute the
      // run/levels within the loop. We just need to quantize the coeffs
      // and measure the distortion.
      result = ComputePSNR();
    }
    if (DBG_PRINT) printf("pass #%d: q=%f value:%.2f\n",
                          p, search_hook_->q, result);

    if (p == 0 || fabs(result - search_hook_->target) < best) {
      // save the matrices for later, if they are better
      for (int c = 0; c < 2; ++c) {
        CopyQuantMatrix(quants_[c].quant_, opt_quants[c]);
      }
      best = fabs(result - search_hook_->target);
      best_q = search_hook_->q;
      best_result = result;
    }
    if (search_hook_->Update(result)) break;
  }
  // transfer back the final matrices
  SetQuantMatrices(opt_quants);
  // return informative values to the user
  search_hook_->q = best_q;
  search_hook_->value = best_result;

  // optimize Huffman table now, if we haven't already during the search
  if (!search_hook_->for_size) {
    StoreRunLevels(base_coeffs);
    if (optimize_size_) {
      StoreOptimalHuffmanTables(nb_mbs, base_coeffs);
    }
  }

  // finish bitstream
  WriteDQT();
  WriteSOF();
  WriteDHT();
  WriteSOS();
  FinalPassScan(nb_mbs, base_coeffs);

  delete[] base_coeffs;
}

////////////////////////////////////////////////////////////////////////////////
// Size & PSNR computation, mostly for dichotomy

size_t Encoder::HeaderSize() const {
  size_t size = 0;
  size += 20;    // APP0
  size += app_markers_.size();
  if (exif_.size() > 0) {
    size += 8 + exif_.size();
  }
  if (iccp_.size() > 0) {
    const size_t chunk_size_max = 0xffff - 12 - 4;
    const size_t num_chunks = (iccp_.size() - 1) / chunk_size_max + 1;
    size += num_chunks * (12 + 4 + 2);
    size += iccp_.size();
  }
  if (xmp_.size() > 0) {
    size += 2 + 2 + 29 + xmp_.size();
  }
  size += 2 * 65 + 2 + 2;         // DQT
  size += 8 + 3 * nb_comps_ + 2;  // SOF
  size += 6 + 2 * nb_comps_ + 2;  // SOS
  size += 2;                      // EOI
  // DHT:
  for (int c = 0; c < (nb_comps_ == 1 ? 1 : 2); ++c) {   // luma, chroma
    for (int type = 0; type <= 1; ++type) {               // dc, ac
      const HuffmanTable* const h = Huffman_tables_[type * 2 + c];
      size += 2 + 3 + 16 + h->nb_syms_;
    }
  }
  return size * 8;
}

void Encoder::BlocksSize(int nb_mbs, const DCTCoeffs* coeffs,
                         const RunLevel* rl,
                         BitCounter* const bc) const {
  for (int n = 0; n < nb_mbs; ++n) {
    const DCTCoeffs& c = coeffs[n];
    const int idx = c.idx_;
    const int q_idx = quant_idx_[idx];

    // DC
    const int dc_len = c.dc_code_ & 0x0f;
    const uint32_t code = dc_codes_[q_idx][dc_len];
    bc->AddPackedCode(code);
    bc->AddBits(c.dc_code_ >> 4, dc_len);

    // AC
    const uint32_t* const codes = ac_codes_[q_idx];
    for (int i = 0; i < c.nb_coeffs_; ++i) {
      int run = rl[i].run_;
      while (run & ~15) {        // escapes
        bc->AddPackedCode(codes[0xf0]);
        run -= 16;
      }
      const uint32_t suffix = rl[i].level_;
      const size_t nbits = suffix & 0x0f;
      const int sym = (run << 4) | nbits;
      bc->AddPackedCode(codes[sym]);
      bc->AddBits(suffix >> 4, nbits);
    }
    if (c.last_ < 63) bc->AddPackedCode(codes[0x00]);  // EOB
    rl += c.nb_coeffs_;
  }
}

float Encoder::ComputeSize(const DCTCoeffs* coeffs) {
  InitCodes(false);
  size_t size = HeaderSize();
  BitCounter bc;
  BlocksSize(mb_w_ * mb_h_ * mcu_blocks_, coeffs, all_run_levels_, &bc);
  size += bc.Size();
  return size / 8.f;
}

////////////////////////////////////////////////////////////////////////////////

static double GetPSNR(uint64_t err, uint64_t size) {
  return (err > 0 && size > 0) ? 10. * log10(255. * 255. * size / err) : 99.;
}

float Encoder::ComputePSNR() const {
  uint64_t error = 0;
  const int16_t* in = in_blocks_;
  const size_t nb_mbs = mb_w_ * mb_h_;
  for (size_t n = 0; n < nb_mbs; ++n) {
    for (int c = 0; c < nb_comps_; ++c) {
      const Quantizer* const Q = &quants_[quant_idx_[c]];
      for (int i = 0; i < nb_blocks_[c]; ++i) {
        error += quantize_error_(in, Q);
        in += 64;
      }
    }
  }
  return GetPSNR(error, 64ull * nb_mbs * mcu_blocks_);
}
<commit_msg>make GetPSNR() be the same on ARM and x86<commit_after>// Copyright 2018 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//  Dichotomy loop and default search implementation
//
// Author: Skal (pascal.massimino@gmail.com)

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#include "sjpegi.h"

using namespace sjpeg;

////////////////////////////////////////////////////////////////////////////////
// dichotomy

#define DBG_PRINT 0

// convergence is considered reached if |dq| < kdQLimit.
static const float kdQLimit = 0.15;

static float Clamp(float v, float min, float max) {
  return (v < min) ? min : (v > max) ? max : v;
}

bool SearchHook::Setup(const SjpegEncodeParam& param) {
  for_size = (param.target_mode == SjpegEncodeParam::TARGET_SIZE);
  target = param.target_value;
  tolerance = param.tolerance / 100.;
  qmin = (param.qmin < 0) ? 0 : param.qmin;
  qmax = (param.qmax > 100) ? 100 :
         (param.qmax < param.qmin) ? param.qmin : param.qmax;
  q = Clamp(SjpegEstimateQuality(param.quant_[0], false), qmin, qmax);
  value = 0;   // undefined for at this point
  return true;
}

bool SearchHook::Update(float result) {
  value = result;
  bool done = (fabs(value - target) < tolerance * target);
  if (done) return true;

  if (value > target) {
    qmax = q;
  } else {
    qmin = q;
  }
  const float last_q = q;
  q = (qmin + qmax) / 2.;
  done = (fabs(q - last_q) < kdQLimit);
  if (DBG_PRINT) {
    printf("q=%.2f value:%.1f -> next-q=%.2f\n", last_q, value, q);
  }
  return done;
}

void SearchHook::NextMatrix(int idx, uint8_t dst[64]) {
  SetQuantMatrix(kDefaultMatrices[idx], GetQFactor(q), dst);
}

////////////////////////////////////////////////////////////////////////////////
// Helpers for the search

void Encoder::StoreRunLevels(DCTCoeffs* coeffs) {
  assert(use_extra_memory_);
  assert(reuse_run_levels_);

  const QuantizeBlockFunc quantize_block = use_trellis_ ? TrellisQuantizeBlock
                                                        : quantize_block_;
  if (use_trellis_) InitCodes(true);

  ResetDCs();
  nb_run_levels_ = 0;
  int16_t* in = in_blocks_;
  for (int n = 0; n < mb_w_ * mb_h_; ++n) {
    CheckBuffers();
    for (int c = 0; c < nb_comps_; ++c) {
      for (int i = 0; i < nb_blocks_[c]; ++i) {
        RunLevel* const run_levels = all_run_levels_ + nb_run_levels_;
        const int dc = quantize_block(in, c, &quants_[quant_idx_[c]],
                                      coeffs, run_levels);
        coeffs->dc_code_ = GenerateDCDiffCode(dc, &DCs_[c]);
        nb_run_levels_ += coeffs->nb_coeffs_;
        ++coeffs;
        in += 64;
      }
    }
  }
}

void Encoder::LoopScan() {
  assert(use_extra_memory_);
  assert(reuse_run_levels_);

  if (use_adaptive_quant_) {
    CollectHistograms();
  } else {
    CollectCoeffs();   // we just need the coeffs
  }

  const size_t nb_mbs = mb_w_ * mb_h_ * mcu_blocks_;
  DCTCoeffs* const base_coeffs = new DCTCoeffs[nb_mbs];

  uint8_t opt_quants[2][64];

  // Dichotomy passes
  float best = 0.;     // best distance
  float best_q = 0.;  // informative value to return to the user
  float best_result = 0.;
  for (int p = 0; p < passes_; ++p) {
    // set new matrices to evaluate
    for (int c = 0; c < 2; ++c) {
      search_hook_->NextMatrix(c, quants_[c].quant_);
      FinalizeQuantMatrix(&quants_[c], q_bias_);
    }
    if (use_adaptive_quant_) {
      AnalyseHisto();   // adjust quant_[] matrices
    }

    float result;
    if (search_hook_->for_size) {
      // compute pass to store coeffs / runs / dc_code_
      StoreRunLevels(base_coeffs);
      if (optimize_size_) {
        StoreOptimalHuffmanTables(nb_mbs, base_coeffs);
        if (use_trellis_) InitCodes(true);
      }
      result = ComputeSize(base_coeffs);
    } else {
      // if we're just targeting PSNR, we don't need to compute the
      // run/levels within the loop. We just need to quantize the coeffs
      // and measure the distortion.
      result = ComputePSNR();
    }
    if (DBG_PRINT) printf("pass #%d: q=%f value:%.2f\n",
                          p, search_hook_->q, result);

    if (p == 0 || fabs(result - search_hook_->target) < best) {
      // save the matrices for later, if they are better
      for (int c = 0; c < 2; ++c) {
        CopyQuantMatrix(quants_[c].quant_, opt_quants[c]);
      }
      best = fabs(result - search_hook_->target);
      best_q = search_hook_->q;
      best_result = result;
    }
    if (search_hook_->Update(result)) break;
  }
  // transfer back the final matrices
  SetQuantMatrices(opt_quants);
  // return informative values to the user
  search_hook_->q = best_q;
  search_hook_->value = best_result;

  // optimize Huffman table now, if we haven't already during the search
  if (!search_hook_->for_size) {
    StoreRunLevels(base_coeffs);
    if (optimize_size_) {
      StoreOptimalHuffmanTables(nb_mbs, base_coeffs);
    }
  }

  // finish bitstream
  WriteDQT();
  WriteSOF();
  WriteDHT();
  WriteSOS();
  FinalPassScan(nb_mbs, base_coeffs);

  delete[] base_coeffs;
}

////////////////////////////////////////////////////////////////////////////////
// Size & PSNR computation, mostly for dichotomy

size_t Encoder::HeaderSize() const {
  size_t size = 0;
  size += 20;    // APP0
  size += app_markers_.size();
  if (exif_.size() > 0) {
    size += 8 + exif_.size();
  }
  if (iccp_.size() > 0) {
    const size_t chunk_size_max = 0xffff - 12 - 4;
    const size_t num_chunks = (iccp_.size() - 1) / chunk_size_max + 1;
    size += num_chunks * (12 + 4 + 2);
    size += iccp_.size();
  }
  if (xmp_.size() > 0) {
    size += 2 + 2 + 29 + xmp_.size();
  }
  size += 2 * 65 + 2 + 2;         // DQT
  size += 8 + 3 * nb_comps_ + 2;  // SOF
  size += 6 + 2 * nb_comps_ + 2;  // SOS
  size += 2;                      // EOI
  // DHT:
  for (int c = 0; c < (nb_comps_ == 1 ? 1 : 2); ++c) {   // luma, chroma
    for (int type = 0; type <= 1; ++type) {               // dc, ac
      const HuffmanTable* const h = Huffman_tables_[type * 2 + c];
      size += 2 + 3 + 16 + h->nb_syms_;
    }
  }
  return size * 8;
}

void Encoder::BlocksSize(int nb_mbs, const DCTCoeffs* coeffs,
                         const RunLevel* rl,
                         BitCounter* const bc) const {
  for (int n = 0; n < nb_mbs; ++n) {
    const DCTCoeffs& c = coeffs[n];
    const int idx = c.idx_;
    const int q_idx = quant_idx_[idx];

    // DC
    const int dc_len = c.dc_code_ & 0x0f;
    const uint32_t code = dc_codes_[q_idx][dc_len];
    bc->AddPackedCode(code);
    bc->AddBits(c.dc_code_ >> 4, dc_len);

    // AC
    const uint32_t* const codes = ac_codes_[q_idx];
    for (int i = 0; i < c.nb_coeffs_; ++i) {
      int run = rl[i].run_;
      while (run & ~15) {        // escapes
        bc->AddPackedCode(codes[0xf0]);
        run -= 16;
      }
      const uint32_t suffix = rl[i].level_;
      const size_t nbits = suffix & 0x0f;
      const int sym = (run << 4) | nbits;
      bc->AddPackedCode(codes[sym]);
      bc->AddBits(suffix >> 4, nbits);
    }
    if (c.last_ < 63) bc->AddPackedCode(codes[0x00]);  // EOB
    rl += c.nb_coeffs_;
  }
}

float Encoder::ComputeSize(const DCTCoeffs* coeffs) {
  InitCodes(false);
  size_t size = HeaderSize();
  BitCounter bc;
  BlocksSize(mb_w_ * mb_h_ * mcu_blocks_, coeffs, all_run_levels_, &bc);
  size += bc.Size();
  return size / 8.f;
}

////////////////////////////////////////////////////////////////////////////////

static float GetPSNR(uint64_t err, uint64_t size) {
  // This expression is written such that it gives the same result on ARM
  // and x86 (for large values of err/size in particular). Don't change it!
  return (err > 0 && size > 0) ? -4.3429448f * log(size / (err / 255. / 255.))
                               : 99.f;
}

float Encoder::ComputePSNR() const {
  uint64_t error = 0;
  const int16_t* in = in_blocks_;
  const size_t nb_mbs = mb_w_ * mb_h_;
  for (size_t n = 0; n < nb_mbs; ++n) {
    for (int c = 0; c < nb_comps_; ++c) {
      const Quantizer* const Q = &quants_[quant_idx_[c]];
      for (int i = 0; i < nb_blocks_[c]; ++i) {
        error += quantize_error_(in, Q);
        in += 64;
      }
    }
  }
  return GetPSNR(error, 64ull * nb_mbs * mcu_blocks_);
}
<|endoftext|>


<commit_before>//
//  main.cpp
//  AGPLab1
//
//  Created by Shockk on 27/09/2013.
//  Copyright (c) 2013 Shockk. All rights reserved.
//

#include <stdio.h>
#include <string>

#include <SDL.h>

#if defined(_WIN32) || defined(__linux__)
#define GLEW_STATIC
#include <GL/glew.h>
#endif

#if defined(__APPLE__)
#include <OpenGL/gl.h>
#include <OpenGL/glext.h>
#include <OpenGL/gl3.h>
#include <OpenGL/gl3ext.h>
#endif

#define ATTRIB_VERTEX   0
#define ATTRIB_COLOR    1
#define ATTRIB_NORMAL   2
#define ATTRIB_TEXCOORD 3
#define ATTRIB_INDEX    4

GLfloat vertices[] =
{
    -1.0f,  0.0f,  0.0f,
     0.0f,  1.0f,  0.0f,
     0.0f,  0.0f,  0.0f
};

GLfloat colors[] =
{
    1.0f,  0.0f,  0.0f,
    0.0f,  1.0f,  0.0f,
    0.0f,  0.0f,  1.0f
};

GLfloat vertices2[] =
{
    0.0f,  0.0f,  0.0f,
    0.0f, -1.0f,  0.0f,
    1.0f,  0.0f,  0.0f
};

GLuint vao[2];
GLuint vbo[3];

char * load_file(const char *path, long *len)
{
    char *buffer = NULL;
    long err = 0;

    // open binary file for reading
    FILE *fh = fopen(path, "rb");
    if(!fh)
    {
        fprintf(stderr, "fopen: error\n");
        return NULL;
    }

    // fseek to end
    err = fseek(fh, 0L, SEEK_END);
    if(err != 0)
    {
        fprintf(stderr, "fseek: error\n");
        return NULL;
    }

    // get file size
    *len = ftell(fh);
    if(*len == -1L)
    {
        fprintf(stderr, "ftell: error\n");
        return NULL;
    }

    // fseek to start
    err = fseek(fh, 0L, SEEK_SET);
    if(err != 0)
    {
        fprintf(stderr, "fseek: error\n");
        return NULL;
    }

    // allocate buffer
    buffer = (char *)malloc(*len);
    if(buffer == NULL)
    {
        fprintf(stderr, "malloc: error\n");
        return NULL;
    }

    // read into buffer
    err = fread(buffer, *len, 1, fh);
    if(err != 1)
    {
        fprintf(stderr, "fread: error\n");
        return NULL;
    }

    // close file
    err = fclose(fh);
    if(err == EOF) fprintf(stderr, "fclose: error\n");

    return buffer;
}

SDL_Window * setup_rc(SDL_GLContext *ctx)
{
    if(SDL_Init(SDL_INIT_VIDEO) < 0)
    {
        fprintf(stderr, "SDL_Init: error\n");
        return NULL;
    }

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
    SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);

    SDL_Window *wnd = SDL_CreateWindow("AGPLab1", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
                                       1280, 800,
                                       SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN
                                       | SDL_WINDOW_FULLSCREEN_DESKTOP);
    if(!wnd)
    {
        fprintf(stderr, "SDL_CreateWindow: error\n");
        return NULL;
    }

    *ctx = SDL_GL_CreateContext(wnd);
    if(!*ctx)
    {
        fprintf(stderr, "SDL_GL_CreateContext: error: %s\n", SDL_GetError());
        return NULL;
    }

    // enable vsync
    SDL_GL_SetSwapInterval(1);

    return wnd;
}

void printShaderError(const GLint shader) {
	int maxLength = 0;
	int logLength = 0;
	GLchar *logMessage;

	// Find out how long the error message is
	if (!glIsShader(shader))
		glGetProgramiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
	else
		glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);

	if (maxLength > 0) { // If message has some contents
		logMessage = new GLchar[maxLength];
		if (!glIsShader(shader))
			glGetProgramInfoLog(shader, maxLength, &logLength, logMessage);
		else
			glGetShaderInfoLog(shader,maxLength, &logLength, logMessage);

        fprintf(stderr, "%s\n", logMessage);
		delete [] logMessage;
	}
	// should additionally check for OpenGL errors here
}

GLuint init_shaders(const char *v_path, const char *f_path)
{
    GLuint v_id = glCreateShader(GL_VERTEX_SHADER);
    GLuint f_id = glCreateShader(GL_FRAGMENT_SHADER);

    long v_len, f_len;
    const char *v_src = load_file(v_path, &v_len);
    const char *f_src = load_file(f_path, &f_len);

    glShaderSource(f_id, 1, &f_src, (GLint *)&f_len);
    glShaderSource(v_id, 1, &v_src, (GLint *)&v_len);

    GLint compile_status;

    glCompileShader(v_id);
    glGetShaderiv(v_id, GL_COMPILE_STATUS, &compile_status);
    if(!compile_status)
    {
        fprintf(stderr, "glCompileShader(v_id): error\n");
        printShaderError(v_id);
    }

    glCompileShader(f_id);
    glGetShaderiv(f_id, GL_COMPILE_STATUS, &compile_status);
    if(!compile_status)
    {
        fprintf(stderr, "glCompileShader(f_id): error\n");
        printShaderError(f_id);
    }

    GLuint p_id = glCreateProgram();
    glAttachShader(p_id, v_id);
    glAttachShader(p_id, f_id);

    glBindAttribLocation(p_id, ATTRIB_VERTEX, "a_vVertex");
    glBindAttribLocation(p_id, ATTRIB_COLOR, "a_vColor");
    glBindAttribLocation(p_id, ATTRIB_NORMAL, "a_vNormal");
    glBindAttribLocation(p_id, ATTRIB_TEXCOORD, "a_vTexCoord");

    glLinkProgram(p_id);
    glUseProgram(p_id);

    free((void *)v_src);
    free((void *)f_src);

    return p_id;
}

void init(void)
{
    init_shaders("minimal.vsh", "minimal.fsh");

    glGenVertexArrays(1, &vao[0]);
    glBindVertexArray(vao[0]);

    glGenBuffers(1, &vbo[0]);
    glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
    glBufferData(GL_ARRAY_BUFFER, 3 * 3 * sizeof(float), vertices, GL_STATIC_DRAW);
    glVertexAttribPointer(ATTRIB_VERTEX, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(ATTRIB_VERTEX);

    glGenBuffers(1, &vbo[1]);
    glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
    glBufferData(GL_ARRAY_BUFFER, 3 * 3 * sizeof(float), colors, GL_STATIC_DRAW);
    glVertexAttribPointer(ATTRIB_COLOR, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(ATTRIB_COLOR);

    glGenVertexArrays(1, &vao[1]);
    glBindVertexArray(vao[1]);

    glGenBuffers(1, &vbo[2]);
    glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
    glBufferData(GL_ARRAY_BUFFER, 3 * 3 * sizeof(float), vertices2, GL_STATIC_DRAW);
    glVertexAttribPointer(ATTRIB_VERTEX, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(ATTRIB_VERTEX);

    glBindVertexArray(vao[0]);
}

void draw(SDL_Window * window) {
	// clear the screen - good to use grey as all white or all black triangles will still be visible
	glClearColor(0.5f,0.5f,0.5f,1.0f);
	glClear(GL_COLOR_BUFFER_BIT);

	glBindVertexArray(vao[0]);	// Bind mesh VAO
	glDrawArrays(GL_TRIANGLES, 0, 3);	// draw 3 vertices (one triangle)

	glBindVertexArray(vao[1]);	// Bind mesh VAO
	glDrawArrays(GL_TRIANGLES, 0, 3);	// draw 3 vertices (one triangle)

	// These are deprecated functions. If a core profile has been correctly
	// created, these commands should compile, but wont render anything
	glColor3f(0.5,1.0,1.0);
	glBegin(GL_TRIANGLES);
    glVertex3f(0.5,0.5,0.0);
    glVertex3f(0.7,0.5,0.0);
    glVertex3f(0.5,0.7,0.0);
	glEnd();

    SDL_GL_SwapWindow(window); // swap buffers
}

int main(int argc, const char ** argv)
{
    SDL_GLContext ctx;
    SDL_Window *wnd = setup_rc(&ctx);
    if(!wnd)
    {
        fprintf(stderr, "setup_rc: error\n");
        return 1;
    }

#if defined(_WIN32) || defined(__linux__)
    glewExperimental = true;

    GLenum err = glewInit();
    if(err != GLEW_OK)
    {
        fprintf(stderr, "glewInit: error\n");
        return 1;
    }
#endif

    init();

    SDL_Event e;
    for(unsigned char running=1; running;)
    {
        SDL_PollEvent(&e);

        switch(e.type)
        {
            case SDL_QUIT:
            {
                running = 0;
                break;
            }
            case SDL_KEYDOWN:
            {
                switch(e.key.keysym.sym)
                {
                    case SDLK_ESCAPE:
                        running = 0;
                        break;
                }
                break;
            }
        }

        draw(wnd);
    }

    SDL_DestroyWindow(wnd);
    SDL_Quit();

    return 0;
}
<commit_msg>Reformatted indented and some functions.<commit_after>//
//  main.cpp
//  AGPLab1
//
//  Created by Shockk on 27/09/2013.
//  Copyright (c) 2013 Shockk. All rights reserved.
//

#include <stdio.h>
#include <string>

#include <SDL.h>

#if defined(_WIN32) || defined(__linux__)
#define GLEW_STATIC
#include <GL/glew.h>
#endif

#if defined(__APPLE__)
#include <OpenGL/gl.h>
#include <OpenGL/glext.h>
#include <OpenGL/gl3.h>
#include <OpenGL/gl3ext.h>
#endif

#define ATTRIB_VERTEX   0
#define ATTRIB_COLOR    1
#define ATTRIB_NORMAL   2
#define ATTRIB_TEXCOORD 3
#define ATTRIB_INDEX    4

GLfloat vertices[] =
{
    -1.0f,  0.0f,  0.0f,
    0.0f,  1.0f,  0.0f,
    0.0f,  0.0f,  0.0f
};

GLfloat colors[] =
{
    1.0f,  0.0f,  0.0f,
    0.0f,  1.0f,  0.0f,
    0.0f,  0.0f,  1.0f
};

GLfloat vertices2[] =
{
    0.0f,  0.0f,  0.0f,
    0.0f, -1.0f,  0.0f,
    1.0f,  0.0f,  0.0f
};

GLuint vao[2];
GLuint vbo[3];

char * load_file(const char *path, long *len)
{
    char *buffer = NULL;
    long err = 0;

    // open binary file for reading
    FILE *fh = fopen(path, "rb");
    if(!fh)
    {
        fprintf(stderr, "fopen: error\n");
        return NULL;
    }

    // fseek to end
    err = fseek(fh, 0L, SEEK_END);
    if(err != 0)
    {
        fprintf(stderr, "fseek: error\n");
        return NULL;
    }

    // get file size
    *len = ftell(fh);
    if(*len == -1L)
    {
        fprintf(stderr, "ftell: error\n");
        return NULL;
    }

    // fseek to start
    err = fseek(fh, 0L, SEEK_SET);
    if(err != 0)
    {
        fprintf(stderr, "fseek: error\n");
        return NULL;
    }

    // allocate buffer
    buffer = (char *)malloc(*len);
    if(buffer == NULL)
    {
        fprintf(stderr, "malloc: error\n");
        return NULL;
    }

    // read into buffer
    err = fread(buffer, *len, 1, fh);
    if(err != 1)
    {
        fprintf(stderr, "fread: error\n");
        return NULL;
    }

    // close file
    err = fclose(fh);
    if(err == EOF) fprintf(stderr, "fclose: error\n");

    return buffer;
}

SDL_Window * setup_rc(SDL_GLContext *ctx)
{
    if(SDL_Init(SDL_INIT_VIDEO) < 0)
    {
        fprintf(stderr, "SDL_Init: error\n");
        return NULL;
    }

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
    SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);

    SDL_Window *wnd = SDL_CreateWindow("AGPLab1", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
                                       1280, 800,
                                       SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN
                                       | SDL_WINDOW_FULLSCREEN_DESKTOP);
    if(!wnd)
    {
        fprintf(stderr, "SDL_CreateWindow: error\n");
        return NULL;
    }

    *ctx = SDL_GL_CreateContext(wnd);
    if(!*ctx)
    {
        fprintf(stderr, "SDL_GL_CreateContext: error: %s\n", SDL_GetError());
        return NULL;
    }

    // enable vsync
    SDL_GL_SetSwapInterval(1);

    return wnd;
}

void print_shader_error(GLint shader)
{
    GLint max_len = 0;
    GLint log_len = 0;
    unsigned char is_shader = glIsShader(shader);

    if(is_shader) glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &max_len);
    else glGetProgramiv(shader, GL_INFO_LOG_LENGTH, &max_len);

    if(max_len > 0)
    {
        GLchar *message = (GLchar *)malloc(sizeof(GLchar) * max_len);

        if(is_shader) glGetShaderInfoLog(shader, max_len, &log_len, message);
        else glGetProgramInfoLog(shader, max_len, &log_len, message);

        fprintf(stderr, "%s\n", message);
        free(message);
    }
}

GLuint init_shaders(const char *v_path, const char *f_path)
{
    GLuint v_id = glCreateShader(GL_VERTEX_SHADER);
    GLuint f_id = glCreateShader(GL_FRAGMENT_SHADER);

    long v_len, f_len;
    const char *v_src = load_file(v_path, &v_len);
    const char *f_src = load_file(f_path, &f_len);

    glShaderSource(f_id, 1, &f_src, (GLint *)&f_len);
    glShaderSource(v_id, 1, &v_src, (GLint *)&v_len);

    GLint compile_status;

    glCompileShader(v_id);
    glGetShaderiv(v_id, GL_COMPILE_STATUS, &compile_status);
    if(!compile_status)
    {
        fprintf(stderr, "glCompileShader(v_id): error\n");
        print_shader_error(v_id);
    }

    glCompileShader(f_id);
    glGetShaderiv(f_id, GL_COMPILE_STATUS, &compile_status);
    if(!compile_status)
    {
        fprintf(stderr, "glCompileShader(f_id): error\n");
        print_shader_error(f_id);
    }

    GLuint p_id = glCreateProgram();
    glAttachShader(p_id, v_id);
    glAttachShader(p_id, f_id);

    glBindAttribLocation(p_id, ATTRIB_VERTEX, "a_vVertex");
    glBindAttribLocation(p_id, ATTRIB_COLOR, "a_vColor");
    glBindAttribLocation(p_id, ATTRIB_NORMAL, "a_vNormal");
    glBindAttribLocation(p_id, ATTRIB_TEXCOORD, "a_vTexCoord");

    glLinkProgram(p_id);
    glUseProgram(p_id);

    free((void *)v_src);
    free((void *)f_src);

    return p_id;
}

void init(void)
{
    init_shaders("minimal.vsh", "minimal.fsh");

    glGenVertexArrays(1, &vao[0]);
    glBindVertexArray(vao[0]);

    glGenBuffers(1, &vbo[0]);
    glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
    glBufferData(GL_ARRAY_BUFFER, 3 * 3 * sizeof(float), vertices, GL_STATIC_DRAW);
    glVertexAttribPointer(ATTRIB_VERTEX, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(ATTRIB_VERTEX);

    glGenBuffers(1, &vbo[1]);
    glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
    glBufferData(GL_ARRAY_BUFFER, 3 * 3 * sizeof(float), colors, GL_STATIC_DRAW);
    glVertexAttribPointer(ATTRIB_COLOR, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(ATTRIB_COLOR);

    glGenVertexArrays(1, &vao[1]);
    glBindVertexArray(vao[1]);

    glGenBuffers(1, &vbo[2]);
    glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
    glBufferData(GL_ARRAY_BUFFER, 3 * 3 * sizeof(float), vertices2, GL_STATIC_DRAW);
    glVertexAttribPointer(ATTRIB_VERTEX, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(ATTRIB_VERTEX);

    glBindVertexArray(vao[0]);
}

void draw(SDL_Window *wnd)
{
    glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glBindVertexArray(vao[0]);
    glDrawArrays(GL_TRIANGLES, 0, 3);

    glBindVertexArray(vao[1]);
    glDrawArrays(GL_TRIANGLES, 0, 3);

    // if core profile is active, should not render anything
    glColor3f(0.5f, 1.0f, 1.0f);
    glBegin(GL_TRIANGLES);
    glVertex3f(0.5f, 0.5f, 0.0f);
    glVertex3f(0.7f, 0.5f, 0.0f);
    glVertex3f(0.5f, 0.7f, 0.0f);

    SDL_GL_SwapWindow(wnd);
}

int main(int argc, const char ** argv)
{
    SDL_GLContext ctx;
    SDL_Window *wnd = setup_rc(&ctx);
    if(!wnd)
    {
        fprintf(stderr, "setup_rc: error\n");
        return 1;
    }

#if defined(_WIN32) || defined(__linux__)
    glewExperimental = true;

    GLenum err = glewInit();
    if(err != GLEW_OK)
    {
        fprintf(stderr, "glewInit: error\n");
        return 1;
    }
#endif

    init();

    SDL_Event e;
    for(unsigned char running=1; running;)
    {
        SDL_PollEvent(&e);

        switch(e.type)
        {
            case SDL_QUIT:
            {
                running = 0;
                break;
            }
            case SDL_KEYDOWN:
            {
                switch(e.key.keysym.sym)
                {
                    case SDLK_ESCAPE:
                        running = 0;
                        break;
                }
                break;
            }
        }

        draw(wnd);
    }

    SDL_DestroyWindow(wnd);
    SDL_Quit();

    return 0;
}
<|endoftext|>


<commit_before>//
//  main.cpp
//  AGPLab1
//
//  Created by Shockk on 27/09/2013.
//  Copyright (c) 2013 Shockk. All rights reserved.
//

#include <stdio.h>
#include <string>

#include <SDL.h>

#if defined(_WIN32) || defined(__linux__)
#define GLEW_STATIC
#include <GL/glew.h>
#endif

#if defined(__APPLE__)
#include <OpenGL/gl.h>
#include <OpenGL/glext.h>
#include <OpenGL/gl3.h>
#include <OpenGL/gl3ext.h>
#endif

#define ATTRIB_VERTEX   0
#define ATTRIB_COLOR    1
#define ATTRIB_NORMAL   2
#define ATTRIB_TEXCOORD 3
#define ATTRIB_INDEX    4

GLfloat vertices[] =
{
    -1.0f,  0.0f,  0.0f,
    0.0f,  1.0f,  0.0f,
    0.0f,  0.0f,  0.0f
};

GLfloat colors[] =
{
    1.0f,  0.0f,  0.0f,
    0.0f,  1.0f,  0.0f,
    0.0f,  0.0f,  1.0f
};

GLfloat vertices2[] =
{
    0.0f,  0.0f,  0.0f,
    0.0f, -1.0f,  0.0f,
    1.0f,  0.0f,  0.0f
};

GLuint vao[2];
GLuint vbo[3];

char * load_file(const char *path, long *len)
{
    char *buffer = NULL;
    long err = 0;

    // open binary file for reading
    FILE *fh = fopen(path, "rb");
    if(!fh)
    {
        fprintf(stderr, "fopen: error\n");
        return NULL;
    }

    // fseek to end
    err = fseek(fh, 0L, SEEK_END);
    if(err != 0)
    {
        fprintf(stderr, "fseek: error\n");
        return NULL;
    }

    // get file size
    *len = ftell(fh);
    if(*len == -1L)
    {
        fprintf(stderr, "ftell: error\n");
        return NULL;
    }

    // fseek to start
    err = fseek(fh, 0L, SEEK_SET);
    if(err != 0)
    {
        fprintf(stderr, "fseek: error\n");
        return NULL;
    }

    // allocate buffer
    buffer = (char *)malloc(*len);
    if(buffer == NULL)
    {
        fprintf(stderr, "malloc: error\n");
        return NULL;
    }

    // read into buffer
    err = fread(buffer, *len, 1, fh);
    if(err != 1)
    {
        fprintf(stderr, "fread: error\n");
        return NULL;
    }

    // close file
    err = fclose(fh);
    if(err == EOF) fprintf(stderr, "fclose: error\n");

    return buffer;
}

SDL_Window * setup_rc(SDL_GLContext *ctx)
{
    if(SDL_Init(SDL_INIT_VIDEO) < 0)
    {
        fprintf(stderr, "SDL_Init: error: %s\n", SDL_GetError());
        return NULL;
    }

    // create dummy window and context to test default options

    SDL_Window *wnd = SDL_CreateWindow("", 0, 0, 0, 0, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN);
    if(!wnd)
    {
        fprintf(stderr, "SDL_CreateWindow: dummy error: %s\n", SDL_GetError());
        return NULL;
    }

    *ctx = SDL_GL_CreateContext(wnd);
    if(!*ctx)
    {
        fprintf(stderr, "SDL_GL_CreateContext: dummy error: %s\n", SDL_GetError());
        return NULL;
    }

    // debug info

    fprintf(stderr, "[DUMMY] OpenGL version: %s\n", glGetString(GL_VERSION));
    fprintf(stderr, "[DUMMY] GLSL version: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION));

    SDL_GL_DeleteContext(*ctx);
    SDL_DestroyWindow(wnd);

    // set attributes and create window and context

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
    //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);

    wnd = SDL_CreateWindow("AGPLab1", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
                                       1280, 720,
                                       SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN
                                       | SDL_WINDOW_BORDERLESS);
    if(!wnd)
    {
        fprintf(stderr, "SDL_CreateWindow: error: %s\n", SDL_GetError());
        return NULL;
    }

    *ctx = SDL_GL_CreateContext(wnd);
    if(!*ctx)
    {
        fprintf(stderr, "SDL_GL_CreateContext: error: %s\n", SDL_GetError());
        return NULL;
    }

    // debug info

    fprintf(stderr, "OpenGL version: %s\n", glGetString(GL_VERSION));
    fprintf(stderr, "GLSL version: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION));

    // enable vsync
    //SDL_GL_SetSwapInterval(1);

    return wnd;
}

void print_shader_error(GLint shader)
{
    GLint max_len = 0;
    GLint log_len = 0;
    unsigned char is_shader = glIsShader(shader);

    if(is_shader) glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &max_len);
    else glGetProgramiv(shader, GL_INFO_LOG_LENGTH, &max_len);

    if(max_len > 0)
    {
        GLchar *message = (GLchar *)malloc(sizeof(GLchar) * max_len);

        if(is_shader) glGetShaderInfoLog(shader, max_len, &log_len, message);
        else glGetProgramInfoLog(shader, max_len, &log_len, message);

        fprintf(stderr, "%s\n", message);
        free(message);
    }
}

GLuint init_shaders(const char *v_path, const char *f_path)
{
    GLuint v_id = glCreateShader(GL_VERTEX_SHADER);
    GLuint f_id = glCreateShader(GL_FRAGMENT_SHADER);

    long v_len, f_len;
    const char *v_src = load_file(v_path, &v_len);
    const char *f_src = load_file(f_path, &f_len);

    glShaderSource(f_id, 1, &f_src, (GLint *)&f_len);
    glShaderSource(v_id, 1, &v_src, (GLint *)&v_len);

    GLint compile_status;

    glCompileShader(v_id);
    glGetShaderiv(v_id, GL_COMPILE_STATUS, &compile_status);
    if(!compile_status)
    {
        fprintf(stderr, "glCompileShader(v_id): error\n");
        print_shader_error(v_id);
    }

    glCompileShader(f_id);
    glGetShaderiv(f_id, GL_COMPILE_STATUS, &compile_status);
    if(!compile_status)
    {
        fprintf(stderr, "glCompileShader(f_id): error\n");
        print_shader_error(f_id);
    }

    GLuint p_id = glCreateProgram();
    glAttachShader(p_id, v_id);
    glAttachShader(p_id, f_id);

    glBindAttribLocation(p_id, ATTRIB_VERTEX, "a_vVertex");
    glBindAttribLocation(p_id, ATTRIB_COLOR, "a_vColor");
    glBindAttribLocation(p_id, ATTRIB_NORMAL, "a_vNormal");
    glBindAttribLocation(p_id, ATTRIB_TEXCOORD, "a_vTexCoord");

    glLinkProgram(p_id);
    glUseProgram(p_id);

    free((void *)v_src);
    free((void *)f_src);

    return p_id;
}

void init(void)
{
    init_shaders("minimal.vsh", "minimal.fsh");

    glGenVertexArrays(1, &vao[0]);
    glBindVertexArray(vao[0]);

    glGenBuffers(1, &vbo[0]);
    glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
    glBufferData(GL_ARRAY_BUFFER, 3 * 3 * sizeof(float), vertices, GL_STATIC_DRAW);
    glVertexAttribPointer(ATTRIB_VERTEX, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(ATTRIB_VERTEX);

    glGenBuffers(1, &vbo[1]);
    glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
    glBufferData(GL_ARRAY_BUFFER, 3 * 3 * sizeof(float), colors, GL_STATIC_DRAW);
    glVertexAttribPointer(ATTRIB_COLOR, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(ATTRIB_COLOR);

    glGenVertexArrays(1, &vao[1]);
    glBindVertexArray(vao[1]);

    glGenBuffers(1, &vbo[2]);
    glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
    glBufferData(GL_ARRAY_BUFFER, 3 * 3 * sizeof(float), vertices2, GL_STATIC_DRAW);
    glVertexAttribPointer(ATTRIB_VERTEX, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(ATTRIB_VERTEX);

    glBindVertexArray(vao[0]);
}

void draw(SDL_Window *wnd)
{
    glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glBindVertexArray(vao[0]);
    glDrawArrays(GL_TRIANGLES, 0, 3);

    glBindVertexArray(vao[1]);
    glDrawArrays(GL_TRIANGLES, 0, 3);

    // if core profile is active, should not render anything
    glColor3f(0.5f, 1.0f, 1.0f);
    glBegin(GL_TRIANGLES);
    glVertex3f(0.5f, 0.5f, 0.0f);
    glVertex3f(0.7f, 0.5f, 0.0f);
    glVertex3f(0.5f, 0.7f, 0.0f);

    SDL_GL_SwapWindow(wnd);
}

int main(int argc, const char ** argv)
{
    SDL_GLContext ctx;
    SDL_Window *wnd = setup_rc(&ctx);
    if(!wnd)
    {
        fprintf(stderr, "setup_rc: error\n");
        return 1;
    }

#if defined(_WIN32) || defined(__linux__)
    glewExperimental = true;

    GLenum err = glewInit();
    if(err != GLEW_OK)
    {
        fprintf(stderr, "glewInit: error\n");
        return 1;
    }
#endif

    init();

    SDL_Event e;
    for(unsigned char running=1; running;)
    {
        SDL_PollEvent(&e);

        switch(e.type)
        {
            case SDL_QUIT:
            {
                running = 0;
                break;
            }
            case SDL_KEYDOWN:
            {
                switch(e.key.keysym.sym)
                {
                    case SDLK_ESCAPE:
                        running = 0;
                        break;
                }
                break;
            }
        }

        draw(wnd);
    }

    SDL_DestroyWindow(wnd);
    SDL_Quit();

    return 0;
}
<commit_msg>Fixed vsync issue on linux and potentially other platforms by processing all new events before drawing, rather than only one per iteration.<commit_after>//
//  main.cpp
//  AGPLab1
//
//  Created by Shockk on 27/09/2013.
//  Copyright (c) 2013 Shockk. All rights reserved.
//

#include <stdio.h>
#include <string>

#include <SDL.h>

#if defined(_WIN32) || defined(__linux__)
#define GLEW_STATIC
#include <GL/glew.h>
#endif

#if defined(__APPLE__)
#include <OpenGL/gl.h>
#include <OpenGL/glext.h>
#include <OpenGL/gl3.h>
#include <OpenGL/gl3ext.h>
#endif

#define ATTRIB_VERTEX   0
#define ATTRIB_COLOR    1
#define ATTRIB_NORMAL   2
#define ATTRIB_TEXCOORD 3
#define ATTRIB_INDEX    4

GLfloat vertices[] =
{
    -1.0f,  0.0f,  0.0f,
    0.0f,  1.0f,  0.0f,
    0.0f,  0.0f,  0.0f
};

GLfloat colors[] =
{
    1.0f,  0.0f,  0.0f,
    0.0f,  1.0f,  0.0f,
    0.0f,  0.0f,  1.0f
};

GLfloat vertices2[] =
{
    0.0f,  0.0f,  0.0f,
    0.0f, -1.0f,  0.0f,
    1.0f,  0.0f,  0.0f
};

GLuint vao[2];
GLuint vbo[3];

char * load_file(const char *path, long *len)
{
    char *buffer = NULL;
    long err = 0;

    // open binary file for reading
    FILE *fh = fopen(path, "rb");
    if(!fh)
    {
        fprintf(stderr, "fopen: error\n");
        return NULL;
    }

    // fseek to end
    err = fseek(fh, 0L, SEEK_END);
    if(err != 0)
    {
        fprintf(stderr, "fseek: error\n");
        return NULL;
    }

    // get file size
    *len = ftell(fh);
    if(*len == -1L)
    {
        fprintf(stderr, "ftell: error\n");
        return NULL;
    }

    // fseek to start
    err = fseek(fh, 0L, SEEK_SET);
    if(err != 0)
    {
        fprintf(stderr, "fseek: error\n");
        return NULL;
    }

    // allocate buffer
    buffer = (char *)malloc(*len);
    if(buffer == NULL)
    {
        fprintf(stderr, "malloc: error\n");
        return NULL;
    }

    // read into buffer
    err = fread(buffer, *len, 1, fh);
    if(err != 1)
    {
        fprintf(stderr, "fread: error\n");
        return NULL;
    }

    // close file
    err = fclose(fh);
    if(err == EOF) fprintf(stderr, "fclose: error\n");

    return buffer;
}

SDL_Window * setup_rc(SDL_GLContext *ctx)
{
    if(SDL_Init(SDL_INIT_VIDEO) < 0)
    {
        fprintf(stderr, "SDL_Init: error: %s\n", SDL_GetError());
        return NULL;
    }

    // create dummy window and context to test default options

    SDL_Window *wnd = SDL_CreateWindow("", 0, 0, 0, 0, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN);
    if(!wnd)
    {
        fprintf(stderr, "SDL_CreateWindow: dummy error: %s\n", SDL_GetError());
        return NULL;
    }

    *ctx = SDL_GL_CreateContext(wnd);
    if(!*ctx)
    {
        fprintf(stderr, "SDL_GL_CreateContext: dummy error: %s\n", SDL_GetError());
        return NULL;
    }

    // debug info

    fprintf(stderr, "[DUMMY] OpenGL version: %s\n", glGetString(GL_VERSION));
    fprintf(stderr, "[DUMMY] GLSL version: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION));

    SDL_GL_DeleteContext(*ctx);
    SDL_DestroyWindow(wnd);

    // set attributes and create window and context

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
    //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);

    wnd = SDL_CreateWindow("AGPLab1", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
                                       1280, 720,
                                       SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN
                                       | SDL_WINDOW_BORDERLESS);
    if(!wnd)
    {
        fprintf(stderr, "SDL_CreateWindow: error: %s\n", SDL_GetError());
        return NULL;
    }

    *ctx = SDL_GL_CreateContext(wnd);
    if(!*ctx)
    {
        fprintf(stderr, "SDL_GL_CreateContext: error: %s\n", SDL_GetError());
        return NULL;
    }

    // debug info

    fprintf(stderr, "OpenGL version: %s\n", glGetString(GL_VERSION));
    fprintf(stderr, "GLSL version: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION));

    // enable vsync
    SDL_GL_SetSwapInterval(1);

    return wnd;
}

void print_shader_error(GLint shader)
{
    GLint max_len = 0;
    GLint log_len = 0;
    unsigned char is_shader = glIsShader(shader);

    if(is_shader) glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &max_len);
    else glGetProgramiv(shader, GL_INFO_LOG_LENGTH, &max_len);

    if(max_len > 0)
    {
        GLchar *message = (GLchar *)malloc(sizeof(GLchar) * max_len);

        if(is_shader) glGetShaderInfoLog(shader, max_len, &log_len, message);
        else glGetProgramInfoLog(shader, max_len, &log_len, message);

        fprintf(stderr, "%s\n", message);
        free(message);
    }
}

GLuint init_shaders(const char *v_path, const char *f_path)
{
    GLuint v_id = glCreateShader(GL_VERTEX_SHADER);
    GLuint f_id = glCreateShader(GL_FRAGMENT_SHADER);

    long v_len, f_len;
    const char *v_src = load_file(v_path, &v_len);
    const char *f_src = load_file(f_path, &f_len);

    glShaderSource(f_id, 1, &f_src, (GLint *)&f_len);
    glShaderSource(v_id, 1, &v_src, (GLint *)&v_len);

    GLint compile_status;

    glCompileShader(v_id);
    glGetShaderiv(v_id, GL_COMPILE_STATUS, &compile_status);
    if(!compile_status)
    {
        fprintf(stderr, "glCompileShader(v_id): error\n");
        print_shader_error(v_id);
    }

    glCompileShader(f_id);
    glGetShaderiv(f_id, GL_COMPILE_STATUS, &compile_status);
    if(!compile_status)
    {
        fprintf(stderr, "glCompileShader(f_id): error\n");
        print_shader_error(f_id);
    }

    GLuint p_id = glCreateProgram();
    glAttachShader(p_id, v_id);
    glAttachShader(p_id, f_id);

    glBindAttribLocation(p_id, ATTRIB_VERTEX, "a_vVertex");
    glBindAttribLocation(p_id, ATTRIB_COLOR, "a_vColor");
    glBindAttribLocation(p_id, ATTRIB_NORMAL, "a_vNormal");
    glBindAttribLocation(p_id, ATTRIB_TEXCOORD, "a_vTexCoord");

    glLinkProgram(p_id);
    glUseProgram(p_id);

    free((void *)v_src);
    free((void *)f_src);

    return p_id;
}

void init(void)
{
    init_shaders("minimal.vsh", "minimal.fsh");

    glGenVertexArrays(1, &vao[0]);
    glBindVertexArray(vao[0]);

    glGenBuffers(1, &vbo[0]);
    glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
    glBufferData(GL_ARRAY_BUFFER, 3 * 3 * sizeof(float), vertices, GL_STATIC_DRAW);
    glVertexAttribPointer(ATTRIB_VERTEX, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(ATTRIB_VERTEX);

    glGenBuffers(1, &vbo[1]);
    glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
    glBufferData(GL_ARRAY_BUFFER, 3 * 3 * sizeof(float), colors, GL_STATIC_DRAW);
    glVertexAttribPointer(ATTRIB_COLOR, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(ATTRIB_COLOR);

    glGenVertexArrays(1, &vao[1]);
    glBindVertexArray(vao[1]);

    glGenBuffers(1, &vbo[2]);
    glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
    glBufferData(GL_ARRAY_BUFFER, 3 * 3 * sizeof(float), vertices2, GL_STATIC_DRAW);
    glVertexAttribPointer(ATTRIB_VERTEX, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(ATTRIB_VERTEX);

    glBindVertexArray(vao[0]);
}

void draw(SDL_Window *wnd)
{
    glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glBindVertexArray(vao[0]);
    glDrawArrays(GL_TRIANGLES, 0, 3);

    glBindVertexArray(vao[1]);
    glDrawArrays(GL_TRIANGLES, 0, 3);

    // if core profile is active, should not render anything
    glColor3f(0.5f, 1.0f, 1.0f);
    glBegin(GL_TRIANGLES);
    glVertex3f(0.5f, 0.5f, 0.0f);
    glVertex3f(0.7f, 0.5f, 0.0f);
    glVertex3f(0.5f, 0.7f, 0.0f);

    SDL_GL_SwapWindow(wnd);
}

int main(int argc, const char ** argv)
{
    SDL_GLContext ctx;
    SDL_Window *wnd = setup_rc(&ctx);
    if(!wnd)
    {
        fprintf(stderr, "setup_rc: error\n");
        return 1;
    }

#if defined(_WIN32) || defined(__linux__)
    glewExperimental = true;

    GLenum err = glewInit();
    if(err != GLEW_OK)
    {
        fprintf(stderr, "glewInit: error\n");
        return 1;
    }
#endif

    init();

    SDL_Event e;
    for(unsigned char running=1; running;)
    {
        unsigned char event_avail = 1;
        for(;;)
        {
            event_avail = SDL_PollEvent(&e);
            if(!event_avail) break;

            switch(e.type)
            {
                case SDL_QUIT:
                {
                    running = 0;
                    break;
                }
                case SDL_KEYDOWN:
                {
                    switch(e.key.keysym.sym)
                    {
                        case SDLK_ESCAPE:
                            running = 0;
                            break;
                    }
                    break;
                }
            }
        }

        draw(wnd);
    }

    SDL_DestroyWindow(wnd);
    SDL_Quit();

    return 0;
}
<|endoftext|>


<commit_before>/*
 Copyright (c) 2015, The Cinder Project: http://libcinder.org All rights reserved.
 This code is intended for use with the Cinder C++ library: http://libcinder.org

 Portions of this code (C) Paul Houx
 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 "cinder/CameraUi.h"

namespace cinder {

CameraUi::CameraUi()
	: mCamera( nullptr ), mWindowSize( 640, 480 ), mMouseWheelMultiplier( 1.2f ), mMinimumPivotDistance( 1.0f ),
		mEnabled( true ), mLastAction( ACTION_NONE )
{}

CameraUi::CameraUi( CameraPersp *camera, const app::WindowRef &window, int signalPriority )
	: mCamera( camera ), mWindowSize( 640, 480 ), mMouseWheelMultiplier( 1.2f ), mMinimumPivotDistance( 1.0f ),
		mEnabled( true )
{
	connect( window, signalPriority );
}

CameraUi::CameraUi( const CameraUi &rhs )
	: mCamera( rhs.mCamera ), mWindowSize( rhs.mWindowSize ),
		mWindow( rhs.mWindow ), mSignalPriority( rhs.mSignalPriority ),
		mMouseWheelMultiplier( rhs.mMouseWheelMultiplier ), mMinimumPivotDistance( rhs.mMinimumPivotDistance ),
		mEnabled( rhs.mEnabled )
{
	connect( mWindow, mSignalPriority );
}

CameraUi::~CameraUi()
{
	disconnect();
}

CameraUi& CameraUi::operator=( const CameraUi &rhs )
{
	mCamera = rhs.mCamera;
	mWindowSize = rhs.mWindowSize;
	mMouseWheelMultiplier = rhs.mMouseWheelMultiplier;
	mMinimumPivotDistance = rhs.mMinimumPivotDistance;
	mWindow = rhs.mWindow;
	mSignalPriority = rhs.mSignalPriority;
	mEnabled = rhs.mEnabled;
	connect( mWindow, mSignalPriority );
	return *this;
}

//! Connects to mouseDown, mouseDrag, mouseWheel and resize signals of \a window, with optional priority \a signalPriority
void CameraUi::connect( const app::WindowRef &window, int signalPriority )
{
	mWindow = window;
	mSignalPriority = signalPriority;
	if( window ) {
		mMouseDownConnection = window->getSignalMouseDown().connect( signalPriority,
			[this]( app::MouseEvent &event ) { mouseDown( event ); } );
		mMouseUpConnection = window->getSignalMouseUp().connect( signalPriority,
			[this]( app::MouseEvent &event ) { mouseUp( event ); } );
		mMouseDragConnection = window->getSignalMouseDrag().connect( signalPriority,
			[this]( app::MouseEvent &event ) { mouseDrag( event ); } );
		mMouseWheelConnection = window->getSignalMouseWheel().connect( signalPriority,
			[this]( app::MouseEvent &event ) { mouseWheel( event ); } );
		mWindowResizeConnection = window->getSignalResize().connect( signalPriority,
			[this]() {
				setWindowSize( mWindow->getSize() );
				if( mCamera )
					mCamera->setAspectRatio( mWindow->getAspectRatio() );
			}
		);
	}
	else
		disconnect();

	mLastAction = ACTION_NONE;
}

//! Disconnects all signal handlers
void CameraUi::disconnect()
{
	mMouseDownConnection.disconnect();
	mMouseUpConnection.disconnect();
	mMouseDragConnection.disconnect();
	mMouseWheelConnection.disconnect();
	mWindowResizeConnection.disconnect();
	mWindow.reset();
}

signals::Signal<void()>& CameraUi::getSignalCameraChange()
{
	return mSignalCameraChange;
}

void CameraUi::mouseDown( app::MouseEvent &event )
{
	mouseDown( event.getPos() );
	event.setHandled();
}

void CameraUi::mouseUp( app::MouseEvent &event )
{
	mouseUp( event.getPos() );
	event.setHandled();
}

void CameraUi::mouseWheel( app::MouseEvent &event )
{
	mouseWheel( event.getWheelIncrement() );
	event.setHandled();
}

void CameraUi::mouseUp( const ivec2 &mousePos )
{
	mLastAction = ACTION_NONE;
}

void CameraUi::mouseDown( const ivec2 &mousePos )
{
	if( ! mCamera || ! mEnabled )
		return;

	mInitialMousePos = mousePos;
	mInitialCam = *mCamera;
	mInitialPivotDistance = mCamera->getPivotDistance();
	mLastAction = ACTION_NONE;
}

void CameraUi::mouseDrag( app::MouseEvent &event )
{
	bool isLeftDown = event.isLeftDown();
	bool isMiddleDown = event.isMiddleDown() || event.isAltDown();
	bool isRightDown = event.isRightDown() || event.isControlDown();

	if( isMiddleDown )
		isLeftDown = false;

	mouseDrag( event.getPos(), isLeftDown, isMiddleDown, isRightDown );
	event.setHandled();
}

void CameraUi::mouseDrag( const ivec2 &mousePos, bool leftDown, bool middleDown, bool rightDown )
{
	if( ! mCamera || ! mEnabled )
		return;

	int action;
	if( rightDown || ( leftDown && middleDown ) )
		action = ACTION_ZOOM;
	else if( middleDown )
		action = ACTION_PAN;
	else if( leftDown )
		action = ACTION_TUMBLE;
	else
		return;

	if( action != mLastAction ) {
		mInitialCam = *mCamera;
		mInitialPivotDistance = mCamera->getPivotDistance();
		mInitialMousePos = mousePos;
	}

	mLastAction = action;

	if( action == ACTION_ZOOM ) { // zooming
		int mouseDelta = ( mousePos.x - mInitialMousePos.x ) + ( mousePos.y - mInitialMousePos.y );

		float newPivotDistance = powf( 2.71828183f, 2 * -mouseDelta / length( vec2( getWindowSize() ) ) ) * mInitialPivotDistance;
		vec3 oldTarget = mInitialCam.getEyePoint() + mInitialCam.getViewDirection() * mInitialPivotDistance;
		vec3 newEye = oldTarget - mInitialCam.getViewDirection() * newPivotDistance;
		mCamera->setEyePoint( newEye );
		mCamera->setPivotDistance( std::max<float>( newPivotDistance, mMinimumPivotDistance ) );
	}
	else if( action == ACTION_PAN ) { // panning
		float deltaX = ( mousePos.x - mInitialMousePos.x ) / (float)getWindowSize().x * mInitialPivotDistance;
		float deltaY = ( mousePos.y - mInitialMousePos.y ) / (float)getWindowSize().y * mInitialPivotDistance;
		vec3 right, up;
		mInitialCam.getBillboardVectors( &right, &up );
		mCamera->setEyePoint( mInitialCam.getEyePoint() - right * deltaX + up * deltaY );
	}
	else { // tumbling
		float deltaX = ( mousePos.x - mInitialMousePos.x ) / -100.0f;
		float deltaY = ( mousePos.y - mInitialMousePos.y ) / 100.0f;
		vec3 mW = normalize( mInitialCam.getViewDirection() );
		bool invertMotion = ( mInitialCam.getOrientation() * glm::vec3( 0, 1, 0 ) ).y < 0.0f;
		vec3 mU = normalize( cross( vec3( 0, 1, 0 ), mW ) );

		if( invertMotion ) {
			deltaX = -deltaX;
			deltaY = -deltaY;
		}

		glm::vec3 rotatedVec = glm::angleAxis( deltaY, mU ) * ( -mInitialCam.getViewDirection() * mInitialPivotDistance );
		rotatedVec = glm::angleAxis( deltaX, glm::vec3( 0, 1, 0 ) ) * rotatedVec;

		mCamera->setEyePoint( mInitialCam.getEyePoint() + mInitialCam.getViewDirection() * mInitialPivotDistance + rotatedVec );
		mCamera->setOrientation( glm::angleAxis( deltaX, glm::vec3( 0, 1, 0 ) ) * glm::angleAxis( deltaY, mU ) * mInitialCam.getOrientation() );
	}

	mSignalCameraChange.emit();
}

void CameraUi::mouseWheel( float increment )
{
	if( ! mCamera || ! mEnabled )
		return;

	// some mice issue mouseWheel events during middle-clicks; filter that out
	if( mLastAction != ACTION_NONE )
		return;

	float multiplier;
	if( mMouseWheelMultiplier > 0 )
		multiplier = powf( mMouseWheelMultiplier, increment );
	else
		multiplier = powf( -mMouseWheelMultiplier, -increment );
	vec3 newEye = mCamera->getEyePoint() + mCamera->getViewDirection() * ( mCamera->getPivotDistance() * ( 1 - multiplier ) );
	mCamera->setEyePoint( newEye );
	mCamera->setPivotDistance( std::max<float>( mCamera->getPivotDistance() * multiplier, mMinimumPivotDistance ) );

	mSignalCameraChange.emit();
}

ivec2 CameraUi::getWindowSize() const
{
	if( mWindow )
		return mWindow->getSize();
	else
		return mWindowSize;
}

}; // namespace cinder
<commit_msg>CameraUi Tumble Orientation<commit_after>/*
 Copyright (c) 2015, The Cinder Project: http://libcinder.org All rights reserved.
 This code is intended for use with the Cinder C++ library: http://libcinder.org

 Portions of this code (C) Paul Houx
 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 "cinder/CameraUi.h"

namespace cinder {

CameraUi::CameraUi()
	: mCamera( nullptr ), mWindowSize( 640, 480 ), mMouseWheelMultiplier( 1.2f ), mMinimumPivotDistance( 1.0f ),
		mEnabled( true ), mLastAction( ACTION_NONE )
{}

CameraUi::CameraUi( CameraPersp *camera, const app::WindowRef &window, int signalPriority )
	: mCamera( camera ), mWindowSize( 640, 480 ), mMouseWheelMultiplier( 1.2f ), mMinimumPivotDistance( 1.0f ),
		mEnabled( true )
{
	connect( window, signalPriority );
}

CameraUi::CameraUi( const CameraUi &rhs )
	: mCamera( rhs.mCamera ), mWindowSize( rhs.mWindowSize ),
		mWindow( rhs.mWindow ), mSignalPriority( rhs.mSignalPriority ),
		mMouseWheelMultiplier( rhs.mMouseWheelMultiplier ), mMinimumPivotDistance( rhs.mMinimumPivotDistance ),
		mEnabled( rhs.mEnabled )
{
	connect( mWindow, mSignalPriority );
}

CameraUi::~CameraUi()
{
	disconnect();
}

CameraUi& CameraUi::operator=( const CameraUi &rhs )
{
	mCamera = rhs.mCamera;
	mWindowSize = rhs.mWindowSize;
	mMouseWheelMultiplier = rhs.mMouseWheelMultiplier;
	mMinimumPivotDistance = rhs.mMinimumPivotDistance;
	mWindow = rhs.mWindow;
	mSignalPriority = rhs.mSignalPriority;
	mEnabled = rhs.mEnabled;
	connect( mWindow, mSignalPriority );
	return *this;
}

//! Connects to mouseDown, mouseDrag, mouseWheel and resize signals of \a window, with optional priority \a signalPriority
void CameraUi::connect( const app::WindowRef &window, int signalPriority )
{
	mWindow = window;
	mSignalPriority = signalPriority;
	if( window ) {
		mMouseDownConnection = window->getSignalMouseDown().connect( signalPriority,
			[this]( app::MouseEvent &event ) { mouseDown( event ); } );
		mMouseUpConnection = window->getSignalMouseUp().connect( signalPriority,
			[this]( app::MouseEvent &event ) { mouseUp( event ); } );
		mMouseDragConnection = window->getSignalMouseDrag().connect( signalPriority,
			[this]( app::MouseEvent &event ) { mouseDrag( event ); } );
		mMouseWheelConnection = window->getSignalMouseWheel().connect( signalPriority,
			[this]( app::MouseEvent &event ) { mouseWheel( event ); } );
		mWindowResizeConnection = window->getSignalResize().connect( signalPriority,
			[this]() {
				setWindowSize( mWindow->getSize() );
				if( mCamera )
					mCamera->setAspectRatio( mWindow->getAspectRatio() );
			}
		);
	}
	else
		disconnect();

	mLastAction = ACTION_NONE;
}

//! Disconnects all signal handlers
void CameraUi::disconnect()
{
	mMouseDownConnection.disconnect();
	mMouseUpConnection.disconnect();
	mMouseDragConnection.disconnect();
	mMouseWheelConnection.disconnect();
	mWindowResizeConnection.disconnect();
	mWindow.reset();
}

signals::Signal<void()>& CameraUi::getSignalCameraChange()
{
	return mSignalCameraChange;
}

void CameraUi::mouseDown( app::MouseEvent &event )
{
	mouseDown( event.getPos() );
	event.setHandled();
}

void CameraUi::mouseUp( app::MouseEvent &event )
{
	mouseUp( event.getPos() );
	event.setHandled();
}

void CameraUi::mouseWheel( app::MouseEvent &event )
{
	mouseWheel( event.getWheelIncrement() );
	event.setHandled();
}

void CameraUi::mouseUp( const ivec2 &mousePos )
{
	mLastAction = ACTION_NONE;
}

void CameraUi::mouseDown( const ivec2 &mousePos )
{
	if( ! mCamera || ! mEnabled )
		return;

	mInitialMousePos = mousePos;
	mInitialCam = *mCamera;
	mInitialPivotDistance = mCamera->getPivotDistance();
	mLastAction = ACTION_NONE;
}

void CameraUi::mouseDrag( app::MouseEvent &event )
{
	bool isLeftDown = event.isLeftDown();
	bool isMiddleDown = event.isMiddleDown() || event.isAltDown();
	bool isRightDown = event.isRightDown() || event.isControlDown();

	if( isMiddleDown )
		isLeftDown = false;

	mouseDrag( event.getPos(), isLeftDown, isMiddleDown, isRightDown );
	event.setHandled();
}

void CameraUi::mouseDrag( const ivec2 &mousePos, bool leftDown, bool middleDown, bool rightDown )
{
	if( ! mCamera || ! mEnabled )
		return;

	int action;
	if( rightDown || ( leftDown && middleDown ) )
		action = ACTION_ZOOM;
	else if( middleDown )
		action = ACTION_PAN;
	else if( leftDown )
		action = ACTION_TUMBLE;
	else
		return;

	if( action != mLastAction ) {
		mInitialCam = *mCamera;
		mInitialPivotDistance = mCamera->getPivotDistance();
		mInitialMousePos = mousePos;
	}

	mLastAction = action;

	if( action == ACTION_ZOOM ) { // zooming
		int mouseDelta = ( mousePos.x - mInitialMousePos.x ) + ( mousePos.y - mInitialMousePos.y );

		float newPivotDistance = powf( 2.71828183f, 2 * -mouseDelta / length( vec2( getWindowSize() ) ) ) * mInitialPivotDistance;
		vec3 oldTarget = mInitialCam.getEyePoint() + mInitialCam.getViewDirection() * mInitialPivotDistance;
		vec3 newEye = oldTarget - mInitialCam.getViewDirection() * newPivotDistance;
		mCamera->setEyePoint( newEye );
		mCamera->setPivotDistance( std::max<float>( newPivotDistance, mMinimumPivotDistance ) );
	}
	else if( action == ACTION_PAN ) { // panning
		float deltaX = ( mousePos.x - mInitialMousePos.x ) / (float)getWindowSize().x * mInitialPivotDistance;
		float deltaY = ( mousePos.y - mInitialMousePos.y ) / (float)getWindowSize().y * mInitialPivotDistance;
		vec3 right, up;
		mInitialCam.getBillboardVectors( &right, &up );
		mCamera->setEyePoint( mInitialCam.getEyePoint() - right * deltaX + up * deltaY );
	}
	else { // tumbling
		float deltaX = ( mousePos.x - mInitialMousePos.x ) / -100.0f;
		float deltaY = ( mousePos.y - mInitialMousePos.y ) / 100.0f;
		vec3 mW = normalize( mInitialCam.getViewDirection() );
		bool invertMotion = glm::length(mInitialCam.getOrientation() * mInitialCam.getWorldUp()) < 0.0f;

		vec3 mU = normalize(cross(mInitialCam.getWorldUp(), mW));

		if( invertMotion ) {
			deltaX = -deltaX;
			deltaY = -deltaY;
		}

		glm::vec3 rotatedVec = glm::angleAxis( deltaY, mU ) * ( -mInitialCam.getViewDirection() * mInitialPivotDistance );
		rotatedVec = glm::angleAxis(deltaX, mInitialCam.getWorldUp()) * rotatedVec;

		mCamera->setEyePoint( mInitialCam.getEyePoint() + mInitialCam.getViewDirection() * mInitialPivotDistance + rotatedVec );
		mCamera->setOrientation(glm::angleAxis(deltaX, mInitialCam.getWorldUp()) * glm::angleAxis(deltaY, mU) * mInitialCam.getOrientation());

	}

	mSignalCameraChange.emit();
}

void CameraUi::mouseWheel( float increment )
{
	if( ! mCamera || ! mEnabled )
		return;

	// some mice issue mouseWheel events during middle-clicks; filter that out
	if( mLastAction != ACTION_NONE )
		return;

	float multiplier;
	if( mMouseWheelMultiplier > 0 )
		multiplier = powf( mMouseWheelMultiplier, increment );
	else
		multiplier = powf( -mMouseWheelMultiplier, -increment );
	vec3 newEye = mCamera->getEyePoint() + mCamera->getViewDirection() * ( mCamera->getPivotDistance() * ( 1 - multiplier ) );
	mCamera->setEyePoint( newEye );
	mCamera->setPivotDistance( std::max<float>( mCamera->getPivotDistance() * multiplier, mMinimumPivotDistance ) );

	mSignalCameraChange.emit();
}

ivec2 CameraUi::getWindowSize() const
{
	if( mWindow )
		return mWindow->getSize();
	else
		return mWindowSize;
}

}; // namespace cinder
<|endoftext|>


<commit_before>#ifndef ITERATOR_ITERATOR_HPP_
#define ITERATOR_ITERATOR_HPP_

#include <iterator>
#include <type_traits>
#include <utility>
#include "iterbase.hpp"

// IterIterWrapper and IteratorIterator provide a means to have a container
// of iterators act like a container of the pointed to objects. This is useful
// for combinatorics and similar itertools which need to keep track of
// more than one element at a time.
// an IterIterWrapper<some_collection_type<collection<T>::iterator>>
// behave like some_collection<T> when iterated over or indexed

namespace iter {
  namespace impl {
    template <typename T, typename = void>
    struct HasConstDeref : std::false_type {};

    template <typename T>
    struct HasConstDeref<T, void_t<decltype(*std::declval<const T&>())>>
        : std::true_type {};

    template <typename TopIter>
    class IteratorIterator
        : public std::iterator<std::random_access_iterator_tag,
              typename std::remove_reference<decltype(
                  **std::declval<TopIter>())>::type> {
      using Diff = std::ptrdiff_t;
      static_assert(
          std::is_same<
              typename std::iterator_traits<TopIter>::iterator_category,
              std::random_access_iterator_tag>::value,
          "IteratorIterator only works with random access iterators");

     private:
      TopIter sub_iter;

     public:
      IteratorIterator() = default;
      IteratorIterator(const TopIter& it) : sub_iter{it} {}

      bool operator==(const IteratorIterator& other) const {
        return !(*this != other);
      }

      bool operator!=(const IteratorIterator& other) const {
        return this->sub_iter != other.sub_iter;
      }

      IteratorIterator& operator++() {
        ++this->sub_iter;
        return *this;
      }

      IteratorIterator operator++(int) {
        auto ret = *this;
        ++*this;
        return ret;
      }

      IteratorIterator& operator--() {
        --this->sub_iter;
        return *this;
      }

      IteratorIterator operator--(int) {
        auto ret = *this;
        --*this;
        return ret;
      }

      auto operator*() -> decltype(**sub_iter) {
        return **this->sub_iter;
      }

      auto operator-> () -> decltype(*sub_iter) {
        return *this->sub_iter;
      }

      IteratorIterator& operator+=(Diff n) {
        this->sub_iter += n;
        return *this;
      }

      IteratorIterator operator+(Diff n) const {
        auto it = *this;
        it += n;
        return it;
      }

      friend IteratorIterator operator+(Diff n, IteratorIterator it) {
        it += n;
        return it;
      }

      IteratorIterator& operator-=(Diff n) {
        this->sub_iter -= n;
        return *this;
      }

      IteratorIterator operator-(Diff n) const {
        auto it = *this;
        it -= n;
        return it;
      }

      friend IteratorIterator operator-(Diff n, IteratorIterator it) {
        it -= n;
        return it;
      }

      Diff operator-(const IteratorIterator& rhs) const {
        return this->sub_iter - rhs.sub_iter;
      }

      auto operator[](Diff idx) -> decltype(*sub_iter[idx]) {
        return *sub_iter[idx];
      }

      bool operator<(const IteratorIterator& rhs) const {
        return this->sub_iter < rhs.sub_iter;
      }

      bool operator>(const IteratorIterator& rhs) const {
        return this->sub_iter > rhs.sub_iter;
      }

      bool operator<=(const IteratorIterator& rhs) const {
        return this->sub_iter <= rhs.sub_iter;
      }

      bool operator>=(const IteratorIterator& rhs) const {
        return this->sub_iter >= rhs.sub_iter;
      }
    };

    template <typename Container>
    class IterIterWrapper {
     private:
      Container container;

      using contained_iter = typename Container::value_type;
      using size_type = typename Container::size_type;
      using iterator = IteratorIterator<typename Container::iterator>;
      using const_iterator =
          IteratorIterator<typename Container::const_iterator>;
      using reverse_iterator =
          IteratorIterator<typename Container::reverse_iterator>;
      using const_reverse_iterator =
          IteratorIterator<typename Container::const_reverse_iterator>;

      template <typename U = Container, typename = void>
      struct ConstAtTypeOrVoid : type_is<void> {};

      template <typename U>
      struct ConstAtTypeOrVoid<U,
          void_t<decltype(*std::declval<const U&>().at(0))>>
          : type_is<decltype(*std::declval<const U&>().at(0))> {};

      using const_at_type_or_void_t = typename ConstAtTypeOrVoid<>::type;

      template <typename U = Container, typename = void>
      struct ConstIndexTypeOrVoid : type_is<void> {};

      template <typename U>
      struct ConstIndexTypeOrVoid<U,
          void_t<decltype(*std::declval<const U&>()[0])>>
          : type_is<decltype(*std::declval<const U&>()[0])> {};

      using const_index_type_or_void_t = typename ConstIndexTypeOrVoid<>::type;

     public:
      IterIterWrapper() = default;

      explicit IterIterWrapper(size_type sz) : container(sz) {}

      IterIterWrapper(size_type sz, const contained_iter& val)
          : container(sz, val) {}

      auto at(size_type pos) -> decltype(*container.at(pos)) {
        return *container.at(pos);
      }

      auto at(size_type pos) const -> const_at_type_or_void_t {
        return *container.at(pos);
      }

      auto operator[](size_type pos) noexcept(noexcept(*container[pos]))
          -> decltype(*container[pos]) {
        return *container[pos];
      }

      auto operator[](size_type pos) const noexcept(noexcept(*container[pos]))
          -> const_index_type_or_void_t {
        return *container[pos];
      }

      bool empty() const noexcept {
        return container.empty();
      }

      size_type size() const noexcept {
        return container.size();
      }

      iterator begin() noexcept {
        return {container.begin()};
      }

      iterator end() noexcept {
        return {container.end()};
      }

      const_iterator begin() const noexcept {
        return {container.begin()};
      }

      const_iterator end() const noexcept {
        return {container.end()};
      }

      const_iterator cbegin() const noexcept {
        return {container.cbegin()};
      }

      const_iterator cend() const noexcept {
        return {container.cend()};
      }

      reverse_iterator rbegin() noexcept {
        return {container.rbegin()};
      }

      reverse_iterator rend() noexcept {
        return {container.rend()};
      }

      const_reverse_iterator rbegin() const noexcept {
        return {container.rbegin()};
      }

      const_reverse_iterator rend() const noexcept {
        return {container.rend()};
      }

      const_reverse_iterator crbegin() const noexcept {
        return {container.rbegin()};
      }

      const_reverse_iterator crend() const noexcept {
        return {container.rend()};
      }

      // get() exposes the underlying container.  this allows the
      // itertools to manipulate the iterators in the container
      // and should not be depended on anywhere else.
      Container& get() noexcept {
        return container;
      }

      const Container& get() const noexcept {
        return container;
      }
    };
  }
}

#endif
<commit_msg>Makes IteratorIterators comparable to each other<commit_after>#ifndef ITERATOR_ITERATOR_HPP_
#define ITERATOR_ITERATOR_HPP_

#include <iterator>
#include <type_traits>
#include <utility>
#include "iterbase.hpp"

// IterIterWrapper and IteratorIterator provide a means to have a container
// of iterators act like a container of the pointed to objects. This is useful
// for combinatorics and similar itertools which need to keep track of
// more than one element at a time.
// an IterIterWrapper<some_collection_type<collection<T>::iterator>>
// behave like some_collection<T> when iterated over or indexed

namespace iter {
  namespace impl {
    template <typename T, typename = void>
    struct HasConstDeref : std::false_type {};

    template <typename T>
    struct HasConstDeref<T, void_t<decltype(*std::declval<const T&>())>>
        : std::true_type {};

    template <typename TopIter>
    class IteratorIterator
        : public std::iterator<std::random_access_iterator_tag,
              typename std::remove_reference<decltype(
                  **std::declval<TopIter>())>::type> {
      template <typename> friend class IteratorIterator;
      using Diff = std::ptrdiff_t;
      static_assert(
          std::is_same<
              typename std::iterator_traits<TopIter>::iterator_category,
              std::random_access_iterator_tag>::value,
          "IteratorIterator only works with random access iterators");

     private:
      TopIter sub_iter;

     public:
      IteratorIterator() = default;
      IteratorIterator(const TopIter& it) : sub_iter{it} {}

      const TopIter& get() const {
        return sub_iter;
      }

      template <typename T>
      bool operator==(const IteratorIterator<T>& other) const {
        return !(*this != other);
      }

      template <typename T>
      bool operator!=(const IteratorIterator<T>& other) const {
        return this->sub_iter != other.sub_iter;
      }

      IteratorIterator& operator++() {
        ++this->sub_iter;
        return *this;
      }

      IteratorIterator operator++(int) {
        auto ret = *this;
        ++*this;
        return ret;
      }

      IteratorIterator& operator--() {
        --this->sub_iter;
        return *this;
      }

      IteratorIterator operator--(int) {
        auto ret = *this;
        --*this;
        return ret;
      }

      auto operator*() -> decltype(**sub_iter) {
        return **this->sub_iter;
      }

      auto operator-> () -> decltype(*sub_iter) {
        return *this->sub_iter;
      }

      IteratorIterator& operator+=(Diff n) {
        this->sub_iter += n;
        return *this;
      }

      IteratorIterator operator+(Diff n) const {
        auto it = *this;
        it += n;
        return it;
      }

      friend IteratorIterator operator+(Diff n, IteratorIterator it) {
        it += n;
        return it;
      }

      IteratorIterator& operator-=(Diff n) {
        this->sub_iter -= n;
        return *this;
      }

      IteratorIterator operator-(Diff n) const {
        auto it = *this;
        it -= n;
        return it;
      }

      friend IteratorIterator operator-(Diff n, IteratorIterator it) {
        it -= n;
        return it;
      }

      Diff operator-(const IteratorIterator& rhs) const {
        return this->sub_iter - rhs.sub_iter;
      }

      auto operator[](Diff idx) -> decltype(*sub_iter[idx]) {
        return *sub_iter[idx];
      }

      bool operator<(const IteratorIterator& rhs) const {
        return this->sub_iter < rhs.sub_iter;
      }

      bool operator>(const IteratorIterator& rhs) const {
        return this->sub_iter > rhs.sub_iter;
      }

      bool operator<=(const IteratorIterator& rhs) const {
        return this->sub_iter <= rhs.sub_iter;
      }

      bool operator>=(const IteratorIterator& rhs) const {
        return this->sub_iter >= rhs.sub_iter;
      }
    };

    template <typename Container>
    class IterIterWrapper {
     private:
      Container container;

      using contained_iter = typename Container::value_type;
      using size_type = typename Container::size_type;
      using iterator = IteratorIterator<typename Container::iterator>;
      using const_iterator =
          IteratorIterator<typename Container::const_iterator>;
      using reverse_iterator =
          IteratorIterator<typename Container::reverse_iterator>;
      using const_reverse_iterator =
          IteratorIterator<typename Container::const_reverse_iterator>;

      template <typename U = Container, typename = void>
      struct ConstAtTypeOrVoid : type_is<void> {};

      template <typename U>
      struct ConstAtTypeOrVoid<U,
          void_t<decltype(*std::declval<const U&>().at(0))>>
          : type_is<decltype(*std::declval<const U&>().at(0))> {};

      using const_at_type_or_void_t = typename ConstAtTypeOrVoid<>::type;

      template <typename U = Container, typename = void>
      struct ConstIndexTypeOrVoid : type_is<void> {};

      template <typename U>
      struct ConstIndexTypeOrVoid<U,
          void_t<decltype(*std::declval<const U&>()[0])>>
          : type_is<decltype(*std::declval<const U&>()[0])> {};

      using const_index_type_or_void_t = typename ConstIndexTypeOrVoid<>::type;

     public:
      IterIterWrapper() = default;

      explicit IterIterWrapper(size_type sz) : container(sz) {}

      IterIterWrapper(size_type sz, const contained_iter& val)
          : container(sz, val) {}

      auto at(size_type pos) -> decltype(*container.at(pos)) {
        return *container.at(pos);
      }

      auto at(size_type pos) const -> const_at_type_or_void_t {
        return *container.at(pos);
      }

      auto operator[](size_type pos) noexcept(noexcept(*container[pos]))
          -> decltype(*container[pos]) {
        return *container[pos];
      }

      auto operator[](size_type pos) const noexcept(noexcept(*container[pos]))
          -> const_index_type_or_void_t {
        return *container[pos];
      }

      bool empty() const noexcept {
        return container.empty();
      }

      size_type size() const noexcept {
        return container.size();
      }

      iterator begin() noexcept {
        return {container.begin()};
      }

      iterator end() noexcept {
        return {container.end()};
      }

      const_iterator begin() const noexcept {
        return {container.begin()};
      }

      const_iterator end() const noexcept {
        return {container.end()};
      }

      const_iterator cbegin() const noexcept {
        return {container.cbegin()};
      }

      const_iterator cend() const noexcept {
        return {container.cend()};
      }

      reverse_iterator rbegin() noexcept {
        return {container.rbegin()};
      }

      reverse_iterator rend() noexcept {
        return {container.rend()};
      }

      const_reverse_iterator rbegin() const noexcept {
        return {container.rbegin()};
      }

      const_reverse_iterator rend() const noexcept {
        return {container.rend()};
      }

      const_reverse_iterator crbegin() const noexcept {
        return {container.rbegin()};
      }

      const_reverse_iterator crend() const noexcept {
        return {container.rend()};
      }

      // get() exposes the underlying container.  this allows the
      // itertools to manipulate the iterators in the container
      // and should not be depended on anywhere else.
      Container& get() noexcept {
        return container;
      }

      const Container& get() const noexcept {
        return container;
      }
    };
  }
}

#endif
<|endoftext|>


<commit_before>// @(#) $Id: AliHLTTPCCATracker.cxx 34611 2009-09-04 00:22:05Z sgorbuno $
// **************************************************************************
// This file is property of and copyright by the ALICE HLT Project          *
// ALICE Experiment at CERN, All rights reserved.                           *
//                                                                          *
// Primary Authors: Sergey Gorbunov <sergey.gorbunov@kip.uni-heidelberg.de> *
//                  Ivan Kisel <kisel@kip.uni-heidelberg.de>                *
//                  for The ALICE HLT Project.                              *
//                                                                          *
// Permission to use, copy, modify and distribute this software and its     *
// documentation strictly for non-commercial purposes is hereby granted     *
// without fee, provided that the above copyright notice appears in all     *
// copies and that both the copyright notice and this permission notice     *
// appear in the supporting documentation. The authors make no claims       *
// about the suitability of this software for any purpose. It is            *
// provided "as is" without express or implied warranty.                    *
//                                                                          *
//***************************************************************************

#include "AliHLTTPCCADef.h"
#include "AliHLTTPCCAGPUConfig.h"
#include "AliHLTTPCCATrackerFramework.h"
#include "AliHLTTPCCAGPUTracker.h"
#include "AliHLTTPCCATracker.h"
#include "AliHLTTPCCAMath.h"
#include "AliHLTTPCCAClusterData.h"

#include <windows.h>
#include <winbase.h>

#ifdef HLTCA_STANDALONE
#include <omp.h>
#endif

int AliHLTTPCCATrackerFramework::InitGPU(int sliceCount, int forceDeviceID)
{
	//Initialize GPU Tracker and determine if GPU available
	int retVal;
	if (!fGPULibAvailable)
	{
		printf("GPU Library not loaded\n");
		return(1);
	}
	if (fGPUTrackerAvailable && (retVal = ExitGPU())) return(retVal);
	retVal = fGPUTracker->InitGPU(sliceCount, forceDeviceID);
	fUseGPUTracker = fGPUTrackerAvailable = retVal == 0;
	fGPUSliceCount = sliceCount;
	return(retVal);
}

int AliHLTTPCCATrackerFramework::ExitGPU()
{
	//Uninitialize GPU Tracker
	if (!fGPUTrackerAvailable) return(0);
	fUseGPUTracker = false;
	fGPUTrackerAvailable = false;
	return(fGPUTracker->ExitGPU());
}

void AliHLTTPCCATrackerFramework::SetGPUDebugLevel(int Level, std::ostream *OutFile, std::ostream *GPUOutFile)
{
	//Set Debug Level for GPU Tracker and also for CPU Tracker for comparison reasons
	fGPUTracker->SetDebugLevel(Level, GPUOutFile);
	fGPUDebugLevel = Level;
	for (int i = 0;i < fgkNSlices;i++)
	{
		fCPUTrackers[i].SetGPUDebugLevel(Level, OutFile);
	}
}

int AliHLTTPCCATrackerFramework::SetGPUTracker(bool enable)
{
	//Enable / disable GPU Tracker
	if (enable && !fGPUTrackerAvailable)
	{
		fUseGPUTracker = false;
		return(1);
	}
	fUseGPUTracker = enable;
	return(0);
}

GPUhd() void AliHLTTPCCATrackerFramework::SetOutputControl( AliHLTTPCCASliceOutput::outputControlStruct* val)
{
	//Set Output Control Pointers
	fOutputControl = val;
	fGPUTracker->SetOutputControl(val);
	for (int i = 0;i < fgkNSlices;i++)
	{
		fCPUTrackers[i].SetOutputControl(val);
	}
}

int AliHLTTPCCATrackerFramework::ProcessSlices(int firstSlice, int sliceCount, AliHLTTPCCAClusterData* pClusterData, AliHLTTPCCASliceOutput** pOutput)
{
	//Process sliceCount slices starting from firstslice, in is pClusterData array, out pOutput array
	if (fUseGPUTracker)
	{
		if (fGPUTracker->Reconstruct(pOutput, pClusterData, firstSlice, CAMath::Min(sliceCount, fgkNSlices - firstSlice))) return(1);
	}
	else
	{
#ifdef HLTCA_STANDALONE
		if (fOutputControl->fOutputPtr && omp_get_max_threads() > 1)
		{
			printf("fOutputPtr must not be used with OpenMP\n");
			return(1);
		}

#pragma omp parallel for
#endif
		for (int iSlice = 0;iSlice < CAMath::Min(sliceCount, fgkNSlices - firstSlice);iSlice++)
		{
			fCPUTrackers[firstSlice + iSlice].ReadEvent(&pClusterData[iSlice]);
			fCPUTrackers[firstSlice + iSlice].SetOutput(&pOutput[iSlice]);
			fCPUTrackers[firstSlice + iSlice].Reconstruct();
			fCPUTrackers[firstSlice + iSlice].SetupCommonMemory();
		}
	}

	if (fGPUDebugLevel >= 6 && fUseGPUTracker)
	{
	    fUseGPUTracker = 0;
	    ProcessSlices(firstSlice, sliceCount, pClusterData, pOutput);
	    fUseGPUTracker = 1;
	}

	//printf("Slice Tracks Output: %d\n", pOutput[0].NTracks());
	return(0);
}

unsigned long long int* AliHLTTPCCATrackerFramework::PerfTimer(int GPU, int iSlice, int iTimer)
{
	//Performance information for slice trackers
	return(GPU ? fGPUTracker->PerfTimer(iSlice, iTimer) : fCPUTrackers[iSlice].PerfTimer(iTimer));
}

int AliHLTTPCCATrackerFramework::InitializeSliceParam(int iSlice, AliHLTTPCCAParam &param)
{
	//Initialize Tracker Parameters for a slice
	if (fGPUTrackerAvailable && fGPUTracker->InitializeSliceParam(iSlice, param)) return(1);
	fCPUTrackers[iSlice].Initialize(param);
	return(0);
}

AliHLTTPCCATrackerFramework::AliHLTTPCCATrackerFramework(int allowGPU) :	fGPULibAvailable(false), fGPUTrackerAvailable(false), fUseGPUTracker(false), fGPUDebugLevel(0), fGPUSliceCount(0), fGPUTracker(NULL), fGPULib(NULL), fOutputControl( NULL ), fCPUSliceCount(fgkNSlices)
{
	//Constructor
	HMODULE hGPULib = LoadLibraryEx("cagpu.dll", NULL, NULL);
	if (hGPULib == NULL)
	{
		printf("Error Opening cagpu library\n");
		fGPUTracker = new AliHLTTPCCAGPUTracker;
	}
	else
	{
		FARPROC createFunc = GetProcAddress(hGPULib, "AliHLTTPCCAGPUTrackerNVCCCreate");
		if (createFunc == NULL)
		{
			printf("Error Creating GPU Tracker\n");
			FreeLibrary(hGPULib);
			fGPUTracker = new AliHLTTPCCAGPUTracker;
		}
		else
		{
			AliHLTTPCCAGPUTracker* (*tmp)() = (AliHLTTPCCAGPUTracker* (*)()) createFunc;
			fGPUTracker = tmp();
			fGPULibAvailable = true;
			fGPULib = (void*) (size_t) hGPULib;
		}
	}

	if (allowGPU && fGPULibAvailable)
	{
		fUseGPUTracker = (fGPUTrackerAvailable= (fGPUTracker->InitGPU() == 0));
		fGPUSliceCount = fGPUTrackerAvailable ? fGPUTracker->GetSliceCount() : 0;
	}
}

AliHLTTPCCATrackerFramework::~AliHLTTPCCATrackerFramework()
{
	HMODULE hGPULib = (HMODULE) (size_t) fGPULib;
	if (fGPULib)
	{
		if (fGPUTracker)
		{
			FARPROC destroyFunc = GetProcAddress(hGPULib, "AliHLTTPCCAGPUTrackerNVCCDestroy");
			if (destroyFunc == NULL) printf("Error Freeing GPU Tracker\n");
			else
			{
				void (*tmp)(AliHLTTPCCAGPUTracker*) =  (void (*)(AliHLTTPCCAGPUTracker*)) destroyFunc;
				tmp(fGPUTracker);
			}
		}

		FreeLibrary(hGPULib);
	}
	else if (fGPUTracker)
	{
		delete fGPUTracker;
	}
	fGPULib = NULL;
	fGPUTracker = NULL;
}
<commit_msg>added linux support for lib<commit_after>// @(#) $Id: AliHLTTPCCATracker.cxx 34611 2009-09-04 00:22:05Z sgorbuno $
// **************************************************************************
// This file is property of and copyright by the ALICE HLT Project          *
// ALICE Experiment at CERN, All rights reserved.                           *
//                                                                          *
// Primary Authors: Sergey Gorbunov <sergey.gorbunov@kip.uni-heidelberg.de> *
//                  Ivan Kisel <kisel@kip.uni-heidelberg.de>                *
//                  for The ALICE HLT Project.                              *
//                                                                          *
// Permission to use, copy, modify and distribute this software and its     *
// documentation strictly for non-commercial purposes is hereby granted     *
// without fee, provided that the above copyright notice appears in all     *
// copies and that both the copyright notice and this permission notice     *
// appear in the supporting documentation. The authors make no claims       *
// about the suitability of this software for any purpose. It is            *
// provided "as is" without express or implied warranty.                    *
//                                                                          *
//***************************************************************************

#include "AliHLTTPCCADef.h"
#include "AliHLTTPCCAGPUConfig.h"
#include "AliHLTTPCCATrackerFramework.h"
#include "AliHLTTPCCAGPUTracker.h"
#include "AliHLTTPCCATracker.h"
#include "AliHLTTPCCAMath.h"
#include "AliHLTTPCCAClusterData.h"

#ifdef R__WIN32
#include <windows.h>
#include <winbase.h>
#else
#include <dlfcn.h>
#endif

#ifdef HLTCA_STANDALONE
#include <omp.h>
#endif

int AliHLTTPCCATrackerFramework::InitGPU(int sliceCount, int forceDeviceID)
{
	//Initialize GPU Tracker and determine if GPU available
	int retVal;
	if (!fGPULibAvailable)
	{
		printf("GPU Library not loaded\n");
		return(1);
	}
	if (fGPUTrackerAvailable && (retVal = ExitGPU())) return(retVal);
	retVal = fGPUTracker->InitGPU(sliceCount, forceDeviceID);
	fUseGPUTracker = fGPUTrackerAvailable = retVal == 0;
	fGPUSliceCount = sliceCount;
	return(retVal);
}

int AliHLTTPCCATrackerFramework::ExitGPU()
{
	//Uninitialize GPU Tracker
	if (!fGPUTrackerAvailable) return(0);
	fUseGPUTracker = false;
	fGPUTrackerAvailable = false;
	return(fGPUTracker->ExitGPU());
}

void AliHLTTPCCATrackerFramework::SetGPUDebugLevel(int Level, std::ostream *OutFile, std::ostream *GPUOutFile)
{
	//Set Debug Level for GPU Tracker and also for CPU Tracker for comparison reasons
	fGPUTracker->SetDebugLevel(Level, GPUOutFile);
	fGPUDebugLevel = Level;
	for (int i = 0;i < fgkNSlices;i++)
	{
		fCPUTrackers[i].SetGPUDebugLevel(Level, OutFile);
	}
}

int AliHLTTPCCATrackerFramework::SetGPUTracker(bool enable)
{
	//Enable / disable GPU Tracker
	if (enable && !fGPUTrackerAvailable)
	{
		fUseGPUTracker = false;
		return(1);
	}
	fUseGPUTracker = enable;
	return(0);
}

GPUhd() void AliHLTTPCCATrackerFramework::SetOutputControl( AliHLTTPCCASliceOutput::outputControlStruct* val)
{
	//Set Output Control Pointers
	fOutputControl = val;
	fGPUTracker->SetOutputControl(val);
	for (int i = 0;i < fgkNSlices;i++)
	{
		fCPUTrackers[i].SetOutputControl(val);
	}
}

int AliHLTTPCCATrackerFramework::ProcessSlices(int firstSlice, int sliceCount, AliHLTTPCCAClusterData* pClusterData, AliHLTTPCCASliceOutput** pOutput)
{
	//Process sliceCount slices starting from firstslice, in is pClusterData array, out pOutput array
	if (fUseGPUTracker)
	{
		if (fGPUTracker->Reconstruct(pOutput, pClusterData, firstSlice, CAMath::Min(sliceCount, fgkNSlices - firstSlice))) return(1);
	}
	else
	{
#ifdef HLTCA_STANDALONE
		if (fOutputControl->fOutputPtr && omp_get_max_threads() > 1)
		{
			printf("fOutputPtr must not be used with OpenMP\n");
			return(1);
		}

#pragma omp parallel for
#endif
		for (int iSlice = 0;iSlice < CAMath::Min(sliceCount, fgkNSlices - firstSlice);iSlice++)
		{
			fCPUTrackers[firstSlice + iSlice].ReadEvent(&pClusterData[iSlice]);
			fCPUTrackers[firstSlice + iSlice].SetOutput(&pOutput[iSlice]);
			fCPUTrackers[firstSlice + iSlice].Reconstruct();
			fCPUTrackers[firstSlice + iSlice].SetupCommonMemory();
		}
	}

	if (fGPUDebugLevel >= 6 && fUseGPUTracker)
	{
	    fUseGPUTracker = 0;
	    ProcessSlices(firstSlice, sliceCount, pClusterData, pOutput);
	    fUseGPUTracker = 1;
	}

	//printf("Slice Tracks Output: %d\n", pOutput[0].NTracks());
	return(0);
}

unsigned long long int* AliHLTTPCCATrackerFramework::PerfTimer(int GPU, int iSlice, int iTimer)
{
	//Performance information for slice trackers
	return(GPU ? fGPUTracker->PerfTimer(iSlice, iTimer) : fCPUTrackers[iSlice].PerfTimer(iTimer));
}

int AliHLTTPCCATrackerFramework::InitializeSliceParam(int iSlice, AliHLTTPCCAParam &param)
{
	//Initialize Tracker Parameters for a slice
	if (fGPUTrackerAvailable && fGPUTracker->InitializeSliceParam(iSlice, param)) return(1);
	fCPUTrackers[iSlice].Initialize(param);
	return(0);
}

AliHLTTPCCATrackerFramework::AliHLTTPCCATrackerFramework(int allowGPU) :	fGPULibAvailable(false), fGPUTrackerAvailable(false), fUseGPUTracker(false), fGPUDebugLevel(0), fGPUSliceCount(0), fGPUTracker(NULL), fGPULib(NULL), fOutputControl( NULL ), fCPUSliceCount(fgkNSlices)
{
	//Constructor
#ifdef R__WIN32
	HMODULE hGPULib = LoadLibraryEx("cagpu.dll", NULL, NULL);
#else
	void* hGPULib = dlopen("cagpu.so", RTLD_NOW);
#endif
	if (hGPULib == NULL)
	{
		printf("Error Opening cagpu library\n");
		fGPUTracker = new AliHLTTPCCAGPUTracker;
	}
	else
	{
#ifdef R__WIN32
		FARPROC createFunc = GetProcAddress(hGPULib, "AliHLTTPCCAGPUTrackerNVCCCreate");
#else
		void* createFunc = (void*) dlsym(hGPULib, "AliHLTTPCCAGPUTrackerNVCCCreate");
#endif
		if (createFunc == NULL)
		{
			printf("Error Creating GPU Tracker\n");
#ifdef R__WIN32
			FreeLibrary(hGPULib);
#else
			dlclose(hGPULib);
#endif
			fGPUTracker = new AliHLTTPCCAGPUTracker;
		}
		else
		{
			AliHLTTPCCAGPUTracker* (*tmp)() = (AliHLTTPCCAGPUTracker* (*)()) createFunc;
			fGPUTracker = tmp();
			fGPULibAvailable = true;
			fGPULib = (void*) (size_t) hGPULib;
		}
	}

	if (allowGPU && fGPULibAvailable)
	{
		fUseGPUTracker = (fGPUTrackerAvailable= (fGPUTracker->InitGPU() == 0));
		fGPUSliceCount = fGPUTrackerAvailable ? fGPUTracker->GetSliceCount() : 0;
	}
}

AliHLTTPCCATrackerFramework::~AliHLTTPCCATrackerFramework()
{
#ifdef R__WIN32
	HMODULE hGPULib = (HMODULE) (size_t) fGPULib;
#else
	void* hGPULib = fGPULib;
#endif
	if (fGPULib)
	{
		if (fGPUTracker)
		{
#ifdef R__WIN32
			FARPROC destroyFunc = GetProcAddress(hGPULib, "AliHLTTPCCAGPUTrackerNVCCDestroy");
#else
			void* destroyFunc = (void*) dlsym(hGPULib, "AliHLTTPCCAGPUTrackerNVCCDestroy");
#endif
			if (destroyFunc == NULL) printf("Error Freeing GPU Tracker\n");
			else
			{
				void (*tmp)(AliHLTTPCCAGPUTracker*) =  (void (*)(AliHLTTPCCAGPUTracker*)) destroyFunc;
				tmp(fGPUTracker);
			}
		}

#ifdef R__WIN32
		FreeLibrary(hGPULib);
#else
		dlclose(hGPULib);
#endif
	}
	else if (fGPUTracker)
	{
		delete fGPUTracker;
	}
	fGPULib = NULL;
	fGPUTracker = NULL;
}
<|endoftext|>


<commit_before>#include <boost/locale.hpp>
#include <locale>
#include <iostream>

/*
 * Copyright (c) 2012 Aldebaran Robotics. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the COPYING file.
 */
int main(int argc, char *argv[])
{
  // Create string with one weird (ñ) char
  char iso[] = {'L', 'a', ' ', 'P', 'e', 0xF1, 'a', 0};

  // Use latin1 to convert string to UTF8
  std::string utf8 = boost::locale::conv::to_utf<char>(iso, "Latin1");

  std::cout << "The UTF8 string is: " << utf8 << std::endl;
  std::cout << "The Latin1 string is: " << iso << std::endl;

  return 0;
}

<commit_msg>Example: fix c++11 error<commit_after>#include <boost/locale.hpp>
#include <locale>
#include <iostream>

/*
 * Copyright (c) 2012 Aldebaran Robotics. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the COPYING file.
 */
int main(int argc, char *argv[])
{
  // Create string with one weird (ñ) char
  char iso[] = "La Pe\361a";

  // Use latin1 to convert string to UTF8
  std::string utf8 = boost::locale::conv::to_utf<char>(iso, "Latin1");

  std::cout << "The UTF8 string is: " << utf8 << std::endl;
  std::cout << "The Latin1 string is: " << iso << std::endl;

  return 0;
}

<|endoftext|>