<commit_before>#include "graphics/gl.h"
#include "graphics/shader.h"
#include <string>
#include <iostream>
#include <cstddef>

namespace demoloop {
  GL::GL()
    : maxAnisotropy(1.0f)
    , maxTextureSize(0)
    , maxRenderTargets(1)
    , maxRenderbufferSamples(0)
    , maxTextureUnits(1)
    , state()
  {
    initMatrices();
  }

  GL::~GL() {}

  bool GL::initContext() {
    glEnable(GL_MULTISAMPLE); // TODO: is this doing anything?
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);
    glEnable(GL_BLEND);

    initMaxValues();

    Shader::defaultShader = new Shader();
    Shader::defaultShader->attach();

    glGenBuffers(1, &mVBO);
    glGenBuffers(1, &mIBO);

    state.boundTextures.clear();
    state.boundTextures.resize(maxTextureUnits, 0);

    for (int i = 0; i < (int) state.boundTextures.size(); i++)
    {
      glActiveTexture(GL_TEXTURE0 + i);
      glBindTexture(GL_TEXTURE_2D, 0);
    }

    glActiveTexture(GL_TEXTURE0);
    state.curTextureUnit = 0;

    createDefaultTexture();

    glBindTexture(GL_TEXTURE_2D, state.defaultTexture);
    glVertexAttrib4f(ATTRIB_CONSTANTCOLOR, 1, 1, 1, 1);
    glVertexAttrib4f(ATTRIB_COLOR, 1, 1, 1, 1);

    GLint maxvertexattribs = 1;
    glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxvertexattribs);
    state.enabledAttribArrays = (uint32_t) ((1ull << uint32_t(maxvertexattribs)) - 1);
    useVertexAttribArrays(0);

    return true;
  }

  void GL::initMatrices() {
    matrices.transform.clear();
    matrices.projection.clear();

    matrices.transform.push_back(glm::mat4());
    matrices.projection.push_back(glm::mat4());
  }

  void GL::initMaxValues()
  {
    // We'll need this value to clamp anisotropy.
    if (GLEW_EXT_texture_filter_anisotropic)
      glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy);
    else
      maxAnisotropy = 1.0f;

    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);

    int maxattachments = 1;
    int maxdrawbuffers = 1;

    if (GLEW_VERSION_2_0)
    {
      glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxattachments);
      glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxdrawbuffers);
    }

    maxRenderTargets = std::min(maxattachments, maxdrawbuffers);

    if (GLEW_VERSION_3_0 || GLEW_ARB_framebuffer_object
      || GLEW_EXT_framebuffer_multisample || GLEW_ANGLE_framebuffer_multisample)
    {
      glGetIntegerv(GL_MAX_SAMPLES, &maxRenderbufferSamples);
    }
    else
      maxRenderbufferSamples = 0;

    glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
  }

  void GL::setViewport(const GL::Viewport &v) {
    glViewport(v.x, v.y, v.w, v.h);
    state.viewport = v;
    GLfloat dimensions[4] = {(GLfloat)v.w, (GLfloat)v.h, 0, 0};
    Shader::current->sendFloat("demoloop_ScreenSize", 4, dimensions, 1);
  }

  GL::Viewport GL::getViewport() const
  {
    return state.viewport;
  }

  void GL::pushTransform()
  {
    matrices.transform.push_back(matrices.transform.back());
  }

  void GL::popTransform()
  {
    matrices.transform.pop_back();
  }

  glm::mat4 &GL::getTransform()
  {
    return matrices.transform.back();
  }

  void GL::pushProjection()
  {
    matrices.projection.push_back(matrices.projection.back());
  }

  void GL::popProjection()
  {
    matrices.projection.pop_back();
  }

  glm::mat4 &GL::getProjection()
  {
    return matrices.projection.back();
  }

  void GL::useVertexAttribArrays(uint32_t arraybits)
  {
    uint32_t diff = arraybits ^ state.enabledAttribArrays;

    if (diff == 0)
      return;

    // Max 32 attributes. As of when this was written, no GL driver exposes more
    // than 32. Lets hope that doesn't change...
    for (uint32_t i = 0; i < 32; i++)
    {
      uint32_t bit = 1 << i;

      if (diff & bit)
      {
        if (arraybits & bit)
          glEnableVertexAttribArray(i);
        else
          glDisableVertexAttribArray(i);
      }
    }

    state.enabledAttribArrays = arraybits;

    // glDisableVertexAttribArray will make the constant value for a vertex
    // attribute undefined. We rely on the per-vertex color attribute being
    // white when no per-vertex color is used, so we set it here.
    // FIXME: Is there a better place to do this?
    if ((diff & ATTRIBFLAG_COLOR) && !(arraybits & ATTRIBFLAG_COLOR))
      glVertexAttrib4f(ATTRIB_COLOR, 1.0f, 1.0f, 1.0f, 1.0f);
  }

  GLint GL::getGLWrapMode(Texture::WrapMode wmode)
  {
    switch (wmode)
    {
    case Texture::WRAP_CLAMP:
    default:
      return GL_CLAMP_TO_EDGE;
    case Texture::WRAP_CLAMP_ZERO:
      return GL_CLAMP_TO_BORDER;
    case Texture::WRAP_REPEAT:
      return GL_REPEAT;
    case Texture::WRAP_MIRRORED_REPEAT:
      return GL_MIRRORED_REPEAT;
    }

  }

  void GL::drawArrays(GLenum mode, GLint first, GLsizei count)
  {
    glDrawArrays(mode, first, count);
    // ++stats.drawCalls;
  }

  void GL::drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
  {
    glDrawArraysInstanced(mode, first, count, primcount);
    // ++stats.drawCalls;
  }

  void GL::drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices)
  {
    glDrawElements(mode, count, type, indices);
    // ++stats.drawCalls;
  }

  void GL::deleteTexture(GLuint texture)
  {
    // glDeleteTextures binds texture 0 to all texture units the deleted texture
    // was bound to before deletion.
    for (GLuint &texid : state.boundTextures)
    {
      if (texid == texture)
        texid = 0;
    }

    glDeleteTextures(1, &texture);
  }

  void GL::setTextureWrap(const Texture::Wrap &w)
  {
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, getGLWrapMode(w.s));
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, getGLWrapMode(w.t));
  }

  void GL::bindFramebuffer(GLenum target, GLuint framebuffer) {
    glBindFramebuffer(target, framebuffer);
  }

  void GL::setTextureFilter(Texture::Filter &f)
  {
    GLint gmin, gmag;

    if (f.mipmap == Texture::FILTER_NONE)
    {
      if (f.min == Texture::FILTER_NEAREST)
        gmin = GL_NEAREST;
      else // f.min == Texture::FILTER_LINEAR
        gmin = GL_LINEAR;
    }
    else
    {
      if (f.min == Texture::FILTER_NEAREST && f.mipmap == Texture::FILTER_NEAREST)
        gmin = GL_NEAREST_MIPMAP_NEAREST;
      else if (f.min == Texture::FILTER_NEAREST && f.mipmap == Texture::FILTER_LINEAR)
        gmin = GL_NEAREST_MIPMAP_LINEAR;
      else if (f.min == Texture::FILTER_LINEAR && f.mipmap == Texture::FILTER_NEAREST)
        gmin = GL_LINEAR_MIPMAP_NEAREST;
      else if (f.min == Texture::FILTER_LINEAR && f.mipmap == Texture::FILTER_LINEAR)
        gmin = GL_LINEAR_MIPMAP_LINEAR;
      else
        gmin = GL_LINEAR;
    }

    switch (f.mag)
    {
    case Texture::FILTER_NEAREST:
      gmag = GL_NEAREST;
      break;
    case Texture::FILTER_LINEAR:
    default:
      gmag = GL_LINEAR;
      break;
    }

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gmin);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gmag);

    // if (GLAD_EXT_texture_filter_anisotropic)
    // {
    //   f.anisotropy = std::min(std::max(f.anisotropy, 1.0f), maxAnisotropy);
    //   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, f.anisotropy);
    // }
    // else
      f.anisotropy = 1.0f;
  }

  void GL::bindTexture(GLuint texture)
  {
    if (texture != state.boundTextures[state.curTextureUnit])
    {
      state.boundTextures[state.curTextureUnit] = texture;
      glBindTexture(GL_TEXTURE_2D, texture);
    }
  }

  void GL::prepareDraw() {
    glm::mat4 modelView;
    prepareDraw(modelView);
  }

  void GL::prepareDraw(glm::mat4 modelView) {
    Shader::current->checkSetBuiltinUniforms(modelView);
  }

  void GL::bufferVertices(const Vertex *vertices, size_t count, GLenum usage) {
    glBindBuffer(GL_ARRAY_BUFFER, mVBO);
    glBufferData(GL_ARRAY_BUFFER, count * sizeof(Vertex), &vertices[0].x, usage);
  }

  void GL::lines(const Vertex *coords, size_t count) {
    prepareDraw();

    glBindBuffer(GL_ARRAY_BUFFER, mVBO);
    glBufferData(GL_ARRAY_BUFFER, count * sizeof(Vertex), &coords[0].x, GL_DYNAMIC_DRAW);

    useVertexAttribArrays(ATTRIBFLAG_POS | ATTRIBFLAG_COLOR);

    glVertexAttribPointer(ATTRIB_POS, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) offsetof(Vertex, x));
    glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (GLvoid*) offsetof(Vertex, r));

    glDrawArrays(GL_LINES, 0, count);
  }

  void GL::triangles(const Vertex *coords, size_t count) {
    prepareDraw();

    glBindBuffer(GL_ARRAY_BUFFER, mVBO);
    glBufferData(GL_ARRAY_BUFFER, count * sizeof(Vertex), &coords[0].x, GL_DYNAMIC_DRAW);

    useVertexAttribArrays(ATTRIBFLAG_POS | ATTRIBFLAG_COLOR | ATTRIBFLAG_TEXCOORD);

    glVertexAttribPointer(ATTRIB_POS, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) offsetof(Vertex, x));
    glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) offsetof(Vertex, s));
    glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (GLvoid*) offsetof(Vertex, r));

    glDrawArrays(GL_TRIANGLES, 0, count);
  }

  void GL::triangles(const Triangle *triangleVertices, size_t count) {
    triangles((Vertex *)triangleVertices, count * 3);
  }

  GLuint GL::getDefaultTexture() const {
    return state.defaultTexture;
  }

  void GL::createDefaultTexture()
  {
    // Set the 'default' texture (id 0) as a repeating white pixel. Otherwise,
    // texture2D calls inside a shader would return black when drawing graphics
    // primitives, which would create the need to use different "passthrough"
    // shaders for untextured primitives vs images.

    GLuint curtexture = state.boundTextures[state.curTextureUnit];

    glGenTextures(1, &state.defaultTexture);
    glBindTexture(GL_TEXTURE_2D, state.defaultTexture);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

    GLubyte pix[] = {255, 255, 255, 255};
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, pix);

    bindTexture(curtexture);
  }

  GL gl;
}
<commit_msg>webgl doesn’t support multisampling<commit_after>#include "graphics/gl.h"
#include "graphics/shader.h"
#include <string>
#include <iostream>
#include <cstddef>

namespace demoloop {
  GL::GL()
    : maxAnisotropy(1.0f)
    , maxTextureSize(0)
    , maxRenderTargets(1)
    , maxRenderbufferSamples(0)
    , maxTextureUnits(1)
    , state()
  {
    initMatrices();
  }

  GL::~GL() {}

  bool GL::initContext() {
#ifndef EMSCRIPTEN
    glEnable(GL_MULTISAMPLE); // TODO: is this doing anything?
#endif
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);
    glEnable(GL_BLEND);

    initMaxValues();

    Shader::defaultShader = new Shader();
    Shader::defaultShader->attach();

    glGenBuffers(1, &mVBO);
    glGenBuffers(1, &mIBO);

    state.boundTextures.clear();
    state.boundTextures.resize(maxTextureUnits, 0);

    for (int i = 0; i < (int) state.boundTextures.size(); i++)
    {
      glActiveTexture(GL_TEXTURE0 + i);
      glBindTexture(GL_TEXTURE_2D, 0);
    }

    glActiveTexture(GL_TEXTURE0);
    state.curTextureUnit = 0;

    createDefaultTexture();

    glBindTexture(GL_TEXTURE_2D, state.defaultTexture);
    glVertexAttrib4f(ATTRIB_CONSTANTCOLOR, 1, 1, 1, 1);
    glVertexAttrib4f(ATTRIB_COLOR, 1, 1, 1, 1);

    GLint maxvertexattribs = 1;
    glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxvertexattribs);
    state.enabledAttribArrays = (uint32_t) ((1ull << uint32_t(maxvertexattribs)) - 1);
    useVertexAttribArrays(0);

    return true;
  }

  void GL::initMatrices() {
    matrices.transform.clear();
    matrices.projection.clear();

    matrices.transform.push_back(glm::mat4());
    matrices.projection.push_back(glm::mat4());
  }

  void GL::initMaxValues()
  {
    // We'll need this value to clamp anisotropy.
    if (GLEW_EXT_texture_filter_anisotropic)
      glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy);
    else
      maxAnisotropy = 1.0f;

    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);

    int maxattachments = 1;
    int maxdrawbuffers = 1;

    if (GLEW_VERSION_2_0)
    {
      glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxattachments);
      glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxdrawbuffers);
    }

    maxRenderTargets = std::min(maxattachments, maxdrawbuffers);

    if (GLEW_VERSION_3_0 || GLEW_ARB_framebuffer_object
      || GLEW_EXT_framebuffer_multisample || GLEW_ANGLE_framebuffer_multisample)
    {
      glGetIntegerv(GL_MAX_SAMPLES, &maxRenderbufferSamples);
    }
    else
      maxRenderbufferSamples = 0;

    glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
  }

  void GL::setViewport(const GL::Viewport &v) {
    glViewport(v.x, v.y, v.w, v.h);
    state.viewport = v;
    GLfloat dimensions[4] = {(GLfloat)v.w, (GLfloat)v.h, 0, 0};
    Shader::current->sendFloat("demoloop_ScreenSize", 4, dimensions, 1);
  }

  GL::Viewport GL::getViewport() const
  {
    return state.viewport;
  }

  void GL::pushTransform()
  {
    matrices.transform.push_back(matrices.transform.back());
  }

  void GL::popTransform()
  {
    matrices.transform.pop_back();
  }

  glm::mat4 &GL::getTransform()
  {
    return matrices.transform.back();
  }

  void GL::pushProjection()
  {
    matrices.projection.push_back(matrices.projection.back());
  }

  void GL::popProjection()
  {
    matrices.projection.pop_back();
  }

  glm::mat4 &GL::getProjection()
  {
    return matrices.projection.back();
  }

  void GL::useVertexAttribArrays(uint32_t arraybits)
  {
    uint32_t diff = arraybits ^ state.enabledAttribArrays;

    if (diff == 0)
      return;

    // Max 32 attributes. As of when this was written, no GL driver exposes more
    // than 32. Lets hope that doesn't change...
    for (uint32_t i = 0; i < 32; i++)
    {
      uint32_t bit = 1 << i;

      if (diff & bit)
      {
        if (arraybits & bit)
          glEnableVertexAttribArray(i);
        else
          glDisableVertexAttribArray(i);
      }
    }

    state.enabledAttribArrays = arraybits;

    // glDisableVertexAttribArray will make the constant value for a vertex
    // attribute undefined. We rely on the per-vertex color attribute being
    // white when no per-vertex color is used, so we set it here.
    // FIXME: Is there a better place to do this?
    if ((diff & ATTRIBFLAG_COLOR) && !(arraybits & ATTRIBFLAG_COLOR))
      glVertexAttrib4f(ATTRIB_COLOR, 1.0f, 1.0f, 1.0f, 1.0f);
  }

  GLint GL::getGLWrapMode(Texture::WrapMode wmode)
  {
    switch (wmode)
    {
    case Texture::WRAP_CLAMP:
    default:
      return GL_CLAMP_TO_EDGE;
    case Texture::WRAP_CLAMP_ZERO:
      return GL_CLAMP_TO_BORDER;
    case Texture::WRAP_REPEAT:
      return GL_REPEAT;
    case Texture::WRAP_MIRRORED_REPEAT:
      return GL_MIRRORED_REPEAT;
    }

  }

  void GL::drawArrays(GLenum mode, GLint first, GLsizei count)
  {
    glDrawArrays(mode, first, count);
    // ++stats.drawCalls;
  }

  void GL::drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
  {
    glDrawArraysInstanced(mode, first, count, primcount);
    // ++stats.drawCalls;
  }

  void GL::drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices)
  {
    glDrawElements(mode, count, type, indices);
    // ++stats.drawCalls;
  }

  void GL::deleteTexture(GLuint texture)
  {
    // glDeleteTextures binds texture 0 to all texture units the deleted texture
    // was bound to before deletion.
    for (GLuint &texid : state.boundTextures)
    {
      if (texid == texture)
        texid = 0;
    }

    glDeleteTextures(1, &texture);
  }

  void GL::setTextureWrap(const Texture::Wrap &w)
  {
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, getGLWrapMode(w.s));
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, getGLWrapMode(w.t));
  }

  void GL::bindFramebuffer(GLenum target, GLuint framebuffer) {
    glBindFramebuffer(target, framebuffer);
  }

  void GL::setTextureFilter(Texture::Filter &f)
  {
    GLint gmin, gmag;

    if (f.mipmap == Texture::FILTER_NONE)
    {
      if (f.min == Texture::FILTER_NEAREST)
        gmin = GL_NEAREST;
      else // f.min == Texture::FILTER_LINEAR
        gmin = GL_LINEAR;
    }
    else
    {
      if (f.min == Texture::FILTER_NEAREST && f.mipmap == Texture::FILTER_NEAREST)
        gmin = GL_NEAREST_MIPMAP_NEAREST;
      else if (f.min == Texture::FILTER_NEAREST && f.mipmap == Texture::FILTER_LINEAR)
        gmin = GL_NEAREST_MIPMAP_LINEAR;
      else if (f.min == Texture::FILTER_LINEAR && f.mipmap == Texture::FILTER_NEAREST)
        gmin = GL_LINEAR_MIPMAP_NEAREST;
      else if (f.min == Texture::FILTER_LINEAR && f.mipmap == Texture::FILTER_LINEAR)
        gmin = GL_LINEAR_MIPMAP_LINEAR;
      else
        gmin = GL_LINEAR;
    }

    switch (f.mag)
    {
    case Texture::FILTER_NEAREST:
      gmag = GL_NEAREST;
      break;
    case Texture::FILTER_LINEAR:
    default:
      gmag = GL_LINEAR;
      break;
    }

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gmin);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gmag);

    // if (GLAD_EXT_texture_filter_anisotropic)
    // {
    //   f.anisotropy = std::min(std::max(f.anisotropy, 1.0f), maxAnisotropy);
    //   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, f.anisotropy);
    // }
    // else
      f.anisotropy = 1.0f;
  }

  void GL::bindTexture(GLuint texture)
  {
    if (texture != state.boundTextures[state.curTextureUnit])
    {
      state.boundTextures[state.curTextureUnit] = texture;
      glBindTexture(GL_TEXTURE_2D, texture);
    }
  }

  void GL::prepareDraw() {
    glm::mat4 modelView;
    prepareDraw(modelView);
  }

  void GL::prepareDraw(glm::mat4 modelView) {
    Shader::current->checkSetBuiltinUniforms(modelView);
  }

  void GL::bufferVertices(const Vertex *vertices, size_t count, GLenum usage) {
    glBindBuffer(GL_ARRAY_BUFFER, mVBO);
    glBufferData(GL_ARRAY_BUFFER, count * sizeof(Vertex), &vertices[0].x, usage);
  }

  void GL::lines(const Vertex *coords, size_t count) {
    prepareDraw();

    glBindBuffer(GL_ARRAY_BUFFER, mVBO);
    glBufferData(GL_ARRAY_BUFFER, count * sizeof(Vertex), &coords[0].x, GL_DYNAMIC_DRAW);

    useVertexAttribArrays(ATTRIBFLAG_POS | ATTRIBFLAG_COLOR);

    glVertexAttribPointer(ATTRIB_POS, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) offsetof(Vertex, x));
    glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (GLvoid*) offsetof(Vertex, r));

    glDrawArrays(GL_LINES, 0, count);
  }

  void GL::triangles(const Vertex *coords, size_t count) {
    prepareDraw();

    glBindBuffer(GL_ARRAY_BUFFER, mVBO);
    glBufferData(GL_ARRAY_BUFFER, count * sizeof(Vertex), &coords[0].x, GL_DYNAMIC_DRAW);

    useVertexAttribArrays(ATTRIBFLAG_POS | ATTRIBFLAG_COLOR | ATTRIBFLAG_TEXCOORD);

    glVertexAttribPointer(ATTRIB_POS, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) offsetof(Vertex, x));
    glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) offsetof(Vertex, s));
    glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (GLvoid*) offsetof(Vertex, r));

    glDrawArrays(GL_TRIANGLES, 0, count);
  }

  void GL::triangles(const Triangle *triangleVertices, size_t count) {
    triangles((Vertex *)triangleVertices, count * 3);
  }

  GLuint GL::getDefaultTexture() const {
    return state.defaultTexture;
  }

  void GL::createDefaultTexture()
  {
    // Set the 'default' texture (id 0) as a repeating white pixel. Otherwise,
    // texture2D calls inside a shader would return black when drawing graphics
    // primitives, which would create the need to use different "passthrough"
    // shaders for untextured primitives vs images.

    GLuint curtexture = state.boundTextures[state.curTextureUnit];

    glGenTextures(1, &state.defaultTexture);
    glBindTexture(GL_TEXTURE_2D, state.defaultTexture);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

    GLubyte pix[] = {255, 255, 255, 255};
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, pix);

    bindTexture(curtexture);
  }

  GL gl;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2019 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.
 */

#include "p2a.hpp"

#include "pci.hpp"

namespace host_tool
{

bool P2aDataHandler::sendContents(const std::string& input,
                                  std::uint16_t session)
{
    PciDevice result;
    PciUtilImpl pci;
    PciFilter filter;
    bool found = false;

    filter.vid = aspeedVendorId;
    filter.did = aspeedDeviceId;

    /* Find the ASPEED PCI device entry we want. */
    auto output = pci.getPciDevices(filter);
    for (const auto& d : output)
    {
        std::fprintf(stderr, "[0x%x 0x%x] ", d.vid, d.did);

        /* Verify it's a memory-based bar -- we want bar1. */
        pciaddr_t bar1 = d.bars[1];
        if ((bar1 & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
        {
            /* We want it to not be IO-based access. */
            continue;
        }

        result = d;
        found = true;
        break;
    }

    if (!found)
    {
        return false;
    }

    std::fprintf(stderr, "\n");

    /* We sent the open command before this, so the window should be open and
     * the bridge enabled.
     */
    std::uint32_t value;
    if (!io->read(result.bars[1] | aspeedP2aConfig, sizeof(value), &value))
    {
        if (0 == (value & p2ABridgeEnabled))
        {
            std::fprintf(stderr, "Bridge not enabled.\n");
            return false;
        }
    }

    std::fprintf(stderr, "The bridge is enabled!\n");

    /* Read the configuration via blobs metadata (stat). */

#if 0
    /* Configure the mmio to point there. */
    if (!io->IoWrite(bar | kAspeedP2aBridge, sizeof(phys), &phys)) {
        // Failed to set it up, so fall back.
        std::fprintf(stderr, "Failed to update the bridge address\n");
        return false;
    }
#endif

    return false;
}

} // namespace host_tool
<commit_msg>tools: p2a: read the PCI configuration<commit_after>/*
 * Copyright 2019 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.
 */

#include "p2a.hpp"

#include "pci.hpp"
#include "pci_handler.hpp"

#include <cstring>

namespace host_tool
{

bool P2aDataHandler::sendContents(const std::string& input,
                                  std::uint16_t session)
{
    PciDevice result;
    PciUtilImpl pci;
    PciFilter filter;
    bool found = false;

    filter.vid = aspeedVendorId;
    filter.did = aspeedDeviceId;

    /* Find the ASPEED PCI device entry we want. */
    auto output = pci.getPciDevices(filter);
    for (const auto& d : output)
    {
        std::fprintf(stderr, "[0x%x 0x%x] ", d.vid, d.did);

        /* Verify it's a memory-based bar -- we want bar1. */
        pciaddr_t bar1 = d.bars[1];
        if ((bar1 & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
        {
            /* We want it to not be IO-based access. */
            continue;
        }

        result = d;
        found = true;
        break;
    }

    if (!found)
    {
        return false;
    }

    std::fprintf(stderr, "\n");

    /* We sent the open command before this, so the window should be open and
     * the bridge enabled.
     */
    std::uint32_t value;
    if (!io->read(result.bars[1] | aspeedP2aConfig, sizeof(value), &value))
    {
        if (0 == (value & p2ABridgeEnabled))
        {
            std::fprintf(stderr, "Bridge not enabled.\n");
            return false;
        }
    }

    std::fprintf(stderr, "The bridge is enabled!\n");

    /* Read the configuration via blobs metadata (stat). */
    ipmiblob::StatResponse stat = blob->getStat(session);
    if (stat.metadata.size() != sizeof(blobs::PciConfigResponse))
    {
        std::fprintf(stderr, "Didn't receive expected size of metadata for "
                             "PCI Configuration response\n");
        return false;
    }

    blobs::PciConfigResponse pciResp;
    std::memcpy(&pciResp, stat.metadata.data(), sizeof(pciResp));
    std::fprintf(stderr, "Received address: 0x%x\n", pciResp.address);

#if 0
    /* Configure the mmio to point there. */
    if (!io->IoWrite(bar | kAspeedP2aBridge, sizeof(phys), &phys)) {
        // Failed to set it up, so fall back.
        std::fprintf(stderr, "Failed to update the bridge address\n");
        return false;
    }
#endif

    return false;
}

} // namespace host_tool
<|endoftext|>


<commit_before>//15th program

#include <iostream>

int main(){
  std::cout << "Enter the number : ";
  int num,product=1;
  std::cin >> num;
  while(num){
    product *= num%10;
    num /= 10;
  }
  std::cout << "Product of digits: " << product << std::endl;
  return 0;
}

//16th

#include <iostream>

int main(){
  std::cout << "Enter the number: ";
  int num;
  std::cin >> num;
  while(num){
    std::cout << num%10;
    num /= 10;
  }
  std::cout << std::endl;
  return 0;
}

//17th

#include <iostream>

int main(){
  std::cout << "Enter the number: ";
  int num,reverse,power = 1;
  std::cin >> num;
  while(num){
    reverse += num%10 * power;
    num /= 10;
    power *= 10;
  }
  if(reverse == num){
    std::cout << "The number is palindrome." << std::endl;
  }else{
    std::cout << "The number is not a palindrome." << std::endl;
  }
  return 0;
}

//18th

#include <iostream>
#include <vector>

int main(){
  std::vector<int>freqs(10,0);
  std::cout << "Enter the number: ";
  int num;
  std::cin >> num;
  while(num){
    freqs[num%10]++;
    num /= 10;
  }

  for(int i=0;i<10;i++){
    std::cout << "Frequency of " << i << " " << freqs[i] << std::endl;
  }
}

//19th It is incomplete

#include <iostream>
#include <vector>
#include <string>

int main(){
  std::cout << "Enter the number :";
  int num,reverse,power=1;
  std::cin >> num;
  std::vector<std::string>largeSuf = {"hundred","thousand","million","billion","trillion"};
  std::vector<std::string>tens = {"ten","twenty","thirty","forty","fifty","sixty","seventy","eighty","ninety"};
  std::vector<std::string>uniqueTens = {"eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen"};
  std::string numWords = "";

  while(num){
    reverse += num%10 * power;
    num /= 10;
    power *= 10;
  }

  while(reverse){

    reverse /= 10;
  }

  return 0;
}

//20th

#include <iostream>

int main(){
  std::cout << "Ascii Code "<< "Represents" << std::endl;
  for(int i=0;i<=127;i++){
    char temp = i;
    std::cout << i << "          " << temp << std::endl;
  }
  return 0;
}

//21st

#include <iostream>

int main(){
  std::cout << "Enter a number : " ;
  int num;
  std::cin >> num;
  int power = 0;
  for(int i=num;i>0;i /= 10){
    power++;
  }

  std::cout << "The power of the number is " << power << std::endl;
  return 0;
}

//22nd

#include <iostream>
#include <cmath>

int main(){
  std::cout << "Enter a number : " ;
  int num;
  std::cin >> num;
  int limit = sqrt(num);
  std::cout << "Factors of the given number are : ";
  for(int i=1;i<=limit;i++){
    if(!num%i){
      std::cout << i << "," << num/i;
    }
  }
  std::cout << std::endl;
}

//23rd

#include <iostream>

int main(){
  std::cout << "Enter a number : " ;
  long long num,factorial=1;
  std::cin >> num;
  for(int i=num;i>1;i--){
    factorial *= i;
  }

  std::cout << "The factorial of " << num << " is " << factorial << std::endl;
  return 0;
}

//24th

#include <iostream>

int main(){
  int num1,num2;
  std::cout << "Enter 2 number separated by space or new line: ";
  std::cin >> num1 >> num2;

  while(num1 != num2)
    {
      if(num1 > num2)
	num1 -= num2;
      else
	num2 -= num1;
    }

  std::cout << "The required HCF is " << num1 << std::endl;
  return 0;
}

//25th

#include <iostream>

int main(){
  int num1,num2;
  std::cout << "Enter 2 number separated by space or new line: ";
  std::cin >> num1 >> num2;
  int prod = num1*num2;

  while(num1 != num2)
    {
      if(num1 > num2)
	num1 -= num2;
      else
	num2 -= num1;
    }

  std::cout << "The required LCM is " << prod/num1 << std::endl;
  return 0;
}

//26th

//Author : Kuntal Majumder
//This program takes a number and displays whether it is prime or not
//Note : This wont work on Turbo (Who uses that anyway?)
//Compiled with gcc 5.4

#include <iostream>
#include <math.h>

//Basically a prime number is only divisible by 1 and itself
//So the basic algorithm is to try each and every number smaller than the given
//number and bigger than 1, if it is divisible by anyone of them it is not a prime number

bool isPrime(int num){
  int limit = sqrt(num);//We need math.h for it
  for(int i=2;i<=limit;i++){
    if(!(num%i)){//A little bit of compression, it means num%i == 0
      return false;
    }
  }

  return true;
}

int main(){
  std::cout << "Enter a number: ";
  int num;
  std::cin >> num;
  if(isPrime(num)){
    std::cout << "It is Prime."<< std::endl;
  }else{
    std::cout << "It is not Prime." << std::endl;
  }
  return 0;
}

//27th

#include <iostream>
#include <vector>

int main(){
  std::cout << "Enter a number: ";
  int num;
  std::cin >> num;
  std::vector<bool>primelist(n+1,true);
  std::cout << "The prime numbers are: ";
  for(int i=2;i<=n;i++){
    if(primelist[i]){
      int temp = i, multiplier = 3;
      temp *= 2;
      while(temp <= num){
	primelist[temp] = false;
	multiplier++;
	temp *= multiplier;
      }
      std::cout << i << " ";
    }
  }

  std::cout << std::endl;
  return 0;
}

//28th

#include <iostream>
#include <vector>

int main(){
  std::cout << "Enter a number: ";
  int num,sum=0;
  std::cin >> num;
  std::vector<bool>primelist(n+1,true);
  for(int i=2;i<=n;i++){
    if(primelist[i]){
      int temp = i, multiplier = 3;
      temp *= 2;
      while(temp <= num){
	primelist[temp] = false;
	multiplier++;
	temp *= multiplier;
      }
      sum += i;
    }
  }

  std::cout << "The sum is " << sum << std::endl;
  return 0;
}

//29th

#include <iostream>
#include <cmath>

int main(){
  int num;
  std::cout << "Enter a number : ";
  std::cin >> num;
  std::cout << "The prime factors are: "
    int limit = sqrt(num);
  for(int i=2;i<=limit;i++){
    if(!num%i){
      std::cout << i << std::endl;
    }
    while(!num%i){
      num /= i;
    }
  }
  return 0;
}

//30th

#include <iostream>
#include <cmath>

int main(){
  int num;
  std::cout << "Enter a number : ";
  std::cin >> num;
  int power = 0;
  for(int i=num;i>0;i /= 10){
    power++;
  }
  int armNum = 0;
  while(num){
    armNum += pow(num%10,power);
    num /= 10;
  }
  if(armNum == num){
    std::cout << "It is an ArmStrong number" << std::endl:
  }else{
    std::cout << "It is not an ArmStrong number" << std::endl:
  }
  return 0;
}
<commit_msg>Delete Kuntal.cpp<commit_after><|endoftext|>


<commit_before>/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */

#pragma once

#include <map>
#include <string>

#include <db.h>

#include "exceptions.hpp"
#include "slice.hpp"

namespace ftcxx {

    template<class Comparator, class Handler>
    class CallbackCursor;
    template<class Comparator, class Predicate>
    class BufferedCursor;
    template<class Comparator>
    class SimpleCursor;

    class DBTxn;

    class DBEnv {
    public:
        explicit DBEnv(DB_ENV *e, bool close_on_destroy=false)
            : _env(e),
              _close_on_destroy(close_on_destroy)
        {}

        ~DBEnv() {
            if (_env && _close_on_destroy) {
                close();
            }
        }

        DBEnv(const DBEnv &) = delete;
        DBEnv& operator=(const DBEnv &) = delete;

        DBEnv(DBEnv &&o)
            : _env(nullptr),
              _close_on_destroy(false)
        {
            std::swap(_env, o._env);
            std::swap(_close_on_destroy, o._close_on_destroy);
        }

        DBEnv& operator=(DBEnv &&o) {
            std::swap(_env, o._env);
            std::swap(_close_on_destroy, o._close_on_destroy);
            return *this;
        }

        DB_ENV *env() const { return _env; }

        void close() {
            int r = _env->close(_env, 0);
            handle_ft_retval(r);
            _env = nullptr;
        }

        typedef std::map<std::string, TOKU_ENGINE_STATUS_ROW_S> Status;
        void get_status(Status &status, fs_redzone_state &redzone_state, uint64_t &env_panic, std::string &panic_string) const;

        void log_flush() {
            int r = _env->log_flush(_env, NULL);
            handle_ft_retval(r);
        }

        int checkpointing_set_period(uint32_t period) {
            if (!_env) {
                return EINVAL;
            }
            _env->checkpointing_set_period(_env, period);
            return 0;
        }

        int cleaner_set_iterations(uint32_t iterations) {
            if (!_env) {
                return EINVAL;
            }
            _env->cleaner_set_iterations(_env, iterations);
            return 0;
        }

        int cleaner_set_period(uint32_t period) {
            if (!_env) {
                return EINVAL;
            }
            _env->cleaner_set_period(_env, period);
            return 0;
        }

        int change_fsync_log_period(uint32_t period) {
            if (!_env) {
                return EINVAL;
            }
            _env->change_fsync_log_period(_env, period);
            return 0;
        }

        /**
         * Constructs a Cursor over this DBEnv's directory.
         */
        template<class Comparator, class Handler>
        CallbackCursor<Comparator, Handler> cursor(const DBTxn &txn, Comparator &&cmp, Handler &&handler) const;

        template<class Comparator, class Predicate>
        BufferedCursor<Comparator, Predicate> buffered_cursor(const DBTxn &txn, Comparator &&cmp, Predicate &&filter) const;

        template<class Comparator>
        SimpleCursor<Comparator> simple_cursor(const DBTxn &txn, Comparator &&cmp, Slice &key, Slice &val) const;

    private:
        DB_ENV *_env;
        bool _close_on_destroy;
    };

    class DBEnvBuilder {
        typedef int (*bt_compare_func)(DB *, const DBT *, const DBT *);
        bt_compare_func _bt_compare;

        typedef int (*update_func)(DB *, const DBT *, const DBT *, const DBT *, void (*)(const DBT *, void *), void *);
        update_func _update_function;

        generate_row_for_put_func _generate_row_for_put;
        generate_row_for_del_func _generate_row_for_del;

        uint32_t _cleaner_period;
        uint32_t _cleaner_iterations;
        uint32_t _checkpointing_period;
        uint32_t _fsync_log_period_msec;
        int _fs_redzone;

        uint64_t _lk_max_memory;
        uint64_t _lock_wait_time_msec;

        typedef uint64_t (*get_lock_wait_time_cb_func)(uint64_t);
        get_lock_wait_time_cb_func _get_lock_wait_time_cb;
        lock_timeout_callback _lock_timeout_callback;
        uint64_t (*_loader_memory_size_callback)(void);

        uint32_t _cachesize_gbytes;
        uint32_t _cachesize_bytes;
        uint32_t _cachetable_bucket_mutexes;

        std::string _product_name;

        std::string _lg_dir;
        std::string _tmp_dir;

        bool _direct_io;
        bool _compress_buffers;

    public:
        DBEnvBuilder()
            : _bt_compare(nullptr),
              _update_function(nullptr),
              _generate_row_for_put(nullptr),
              _generate_row_for_del(nullptr),
              _cleaner_period(0),
              _cleaner_iterations(0),
              _checkpointing_period(0),
              _fsync_log_period_msec(0),
              _fs_redzone(0),
              _lk_max_memory(0),
              _lock_wait_time_msec(0),
              _get_lock_wait_time_cb(nullptr),
              _lock_timeout_callback(nullptr),
              _loader_memory_size_callback(nullptr),
              _cachesize_gbytes(0),
              _cachesize_bytes(0),
              _cachetable_bucket_mutexes(0),
              _product_name(""),
              _lg_dir(""),
              _tmp_dir(""),
              _direct_io(false),
              _compress_buffers(true)
        {}

        DBEnv open(const char *env_dir, uint32_t flags, int mode) const {
            db_env_set_direct_io(_direct_io);
            db_env_set_compress_buffers_before_eviction(_compress_buffers);
            if (_cachetable_bucket_mutexes) {
                db_env_set_num_bucket_mutexes(_cachetable_bucket_mutexes);
            }

            if (!_product_name.empty()) {
                db_env_set_toku_product_name(_product_name.c_str());
            }

            DB_ENV *env;
            int r = db_env_create(&env, 0);
            handle_ft_retval(r);

            if (_bt_compare) {
                r = env->set_default_bt_compare(env, _bt_compare);
                handle_ft_retval(r);
            }

            if (_update_function) {
                env->set_update(env, _update_function);
            }

            if (_generate_row_for_put) {
                r = env->set_generate_row_callback_for_put(env, _generate_row_for_put);
                handle_ft_retval(r);
            }

            if (_generate_row_for_del) {
                r = env->set_generate_row_callback_for_del(env, _generate_row_for_del);
                handle_ft_retval(r);
            }

            if (_lk_max_memory) {
                r = env->set_lk_max_memory(env, _lk_max_memory);
                handle_ft_retval(r);
            }

            if (_lock_wait_time_msec || _get_lock_wait_time_cb) {
                uint64_t wait_time = _lock_wait_time_msec;
                if (!wait_time) {
                    r = env->get_lock_timeout(env, &wait_time);
                    handle_ft_retval(r);
                }
                r = env->set_lock_timeout(env, wait_time, _get_lock_wait_time_cb);
                handle_ft_retval(r);
            }

            if (_lock_timeout_callback) {
                r = env->set_lock_timeout_callback(env, _lock_timeout_callback);
                handle_ft_retval(r);
            }

            if (_loader_memory_size_callback) {
                env->set_loader_memory_size(env, _loader_memory_size_callback);
            }

            if (_cachesize_gbytes || _cachesize_bytes) {
                r = env->set_cachesize(env, _cachesize_gbytes, _cachesize_bytes, 1);
                handle_ft_retval(r);
            }

            if (_fs_redzone) {
                env->set_redzone(env, _fs_redzone);
            }

            if (!_lg_dir.empty()) {
                r = env->set_lg_dir(env, _lg_dir.c_str());
                handle_ft_retval(r);
            }

            if (!_tmp_dir.empty()) {
                r = env->set_tmp_dir(env, _tmp_dir.c_str());
                handle_ft_retval(r);
            }

            r = env->open(env, env_dir, flags, mode);
            handle_ft_retval(r);

            if (_cleaner_period) {
                r = env->cleaner_set_period(env, _cleaner_period);
                handle_ft_retval(r);
            }

            if (_cleaner_iterations) {
                r = env->cleaner_set_iterations(env, _cleaner_iterations);
                handle_ft_retval(r);
            }

            if (_checkpointing_period) {
                r = env->checkpointing_set_period(env, _checkpointing_period);
                handle_ft_retval(r);
            }

            if (_fsync_log_period_msec) {
                env->change_fsync_log_period(env, _fsync_log_period_msec);
            }

            return DBEnv(env, true);
        }

        DBEnvBuilder& set_direct_io(bool direct_io) {
            _direct_io = direct_io;
            return *this;
        }

        DBEnvBuilder& set_compress_buffers_before_eviction(bool compress_buffers) {
            _compress_buffers = compress_buffers;
            return *this;
        }

        DBEnvBuilder& set_default_bt_compare(bt_compare_func bt_compare) {
            _bt_compare = bt_compare;
            return *this;
        }

        DBEnvBuilder& set_update(update_func update_function) {
            _update_function = update_function;
            return *this;
        }

        DBEnvBuilder& set_generate_row_callback_for_put(generate_row_for_put_func generate_row_for_put) {
            _generate_row_for_put = generate_row_for_put;
            return *this;
        }

        DBEnvBuilder& set_generate_row_callback_for_del(generate_row_for_del_func generate_row_for_del) {
            _generate_row_for_del = generate_row_for_del;
            return *this;
        }

        DBEnvBuilder& cleaner_set_period(uint32_t period) {
            _cleaner_period = period;
            return *this;
        }

        DBEnvBuilder& cleaner_set_iterations(uint32_t iterations) {
            _cleaner_iterations = iterations;
            return *this;
        }

        DBEnvBuilder& checkpointing_set_period(uint32_t period) {
            _checkpointing_period = period;
            return *this;
        }

        DBEnvBuilder& change_fsync_log_period(uint32_t period) {
            _fsync_log_period_msec = period;
            return *this;
        }

        DBEnvBuilder& set_fs_redzone(int fs_redzone) {
            _fs_redzone = fs_redzone;
            return *this;
        }

        DBEnvBuilder& set_lk_max_memory(uint64_t sz) {
            _lk_max_memory = sz;
            return *this;
        }

        DBEnvBuilder& set_lock_wait_time_msec(uint64_t lock_wait_time_msec) {
            _lock_wait_time_msec = lock_wait_time_msec;
            return *this;
        }

        DBEnvBuilder& set_lock_wait_time_cb(get_lock_wait_time_cb_func get_lock_wait_time_cb) {
            _get_lock_wait_time_cb = get_lock_wait_time_cb;
            return *this;
        }

        DBEnvBuilder& set_lock_timeout_callback(lock_timeout_callback callback) {
            _lock_timeout_callback = callback;
            return *this;
        }

        DBEnvBuilder& set_loader_memory_size(uint64_t (*callback)(void)) {
            _loader_memory_size_callback = callback;
            return *this;
        }

        DBEnvBuilder& set_cachesize(uint32_t gbytes, uint32_t bytes) {
            _cachesize_gbytes = gbytes;
            _cachesize_bytes = bytes;
            return *this;
        }

        DBEnvBuilder& set_cachetable_bucket_mutexes(uint32_t mutexes) {
            _cachetable_bucket_mutexes = mutexes;
            return *this;
        }

        DBEnvBuilder& set_product_name(const char *product_name) {
            _product_name = std::string(product_name);
            return *this;
        }

        DBEnvBuilder& set_lg_dir(const char *lg_dir) {
            _lg_dir = std::string(lg_dir);
            return *this;
        }

        DBEnvBuilder& set_tmp_dir(const char *tmp_dir) {
            _tmp_dir = std::string(tmp_dir);
            return *this;
        }
    };

} // namespace ftcxx
<commit_msg>added engine status to DBEnv<commit_after>/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */

#pragma once

#include <map>
#include <string>

#include <db.h>

#include "exceptions.hpp"
#include "slice.hpp"

namespace ftcxx {

    template<class Comparator, class Handler>
    class CallbackCursor;
    template<class Comparator, class Predicate>
    class BufferedCursor;
    template<class Comparator>
    class SimpleCursor;

    class DBTxn;

    class DBEnv {
    public:
        explicit DBEnv(DB_ENV *e, bool close_on_destroy=false)
            : _env(e),
              _close_on_destroy(close_on_destroy)
        {}

        ~DBEnv() {
            if (_env && _close_on_destroy) {
                close();
            }
        }

        DBEnv(const DBEnv &) = delete;
        DBEnv& operator=(const DBEnv &) = delete;

        DBEnv(DBEnv &&o)
            : _env(nullptr),
              _close_on_destroy(false)
        {
            std::swap(_env, o._env);
            std::swap(_close_on_destroy, o._close_on_destroy);
        }

        DBEnv& operator=(DBEnv &&o) {
            std::swap(_env, o._env);
            std::swap(_close_on_destroy, o._close_on_destroy);
            return *this;
        }

        DB_ENV *env() const { return _env; }

        void close() {
            int r = _env->close(_env, 0);
            handle_ft_retval(r);
            _env = nullptr;
        }

        typedef std::map<std::string, TOKU_ENGINE_STATUS_ROW_S> Status;
        void get_status(Status &status, fs_redzone_state &redzone_state, uint64_t &env_panic, std::string &panic_string) const;

        void log_flush() {
            int r = _env->log_flush(_env, NULL);
            handle_ft_retval(r);
        }

        int checkpointing_set_period(uint32_t period) {
            if (!_env) {
                return EINVAL;
            }
            _env->checkpointing_set_period(_env, period);
            return 0;
        }

        int cleaner_set_iterations(uint32_t iterations) {
            if (!_env) {
                return EINVAL;
            }
            _env->cleaner_set_iterations(_env, iterations);
            return 0;
        }

        int cleaner_set_period(uint32_t period) {
            if (!_env) {
                return EINVAL;
            }
            _env->cleaner_set_period(_env, period);
            return 0;
        }

        int change_fsync_log_period(uint32_t period) {
            if (!_env) {
                return EINVAL;
            }
            _env->change_fsync_log_period(_env, period);
            return 0;
        }

        uint64_t get_engine_status_num_rows() {
            if (!_env) {
                handle_ft_retval(EINVAL); // throws
            }
            uint64_t ret;
            int r = _env->get_engine_status_num_rows(_env, &ret);
            handle_ft_retval(r);
            return ret;
        }

        void get_engine_status(TOKU_ENGINE_STATUS_ROW_S *rows, uint64_t max_rows, uint64_t &num_rows,
                               uint64_t &panic, std::string &panic_string,
                               toku_engine_status_include_type include_type) {
            if (!_env) {
                handle_ft_retval(EINVAL);
            }
            fs_redzone_state dummy;  // this is duplicated in the actual engine status output
            const size_t panic_string_len = 1024;
            char panic_string_buf[panic_string_len];
            panic_string_buf[0] = '\0';
            int r = _env->get_engine_status(_env, rows, max_rows, &num_rows,
                                            &dummy, &panic, panic_string_buf, panic_string_len,
                                            include_type);
            handle_ft_retval(r);
            panic_string = panic_string_buf;
        }

        /**
         * Constructs a Cursor over this DBEnv's directory.
         */
        template<class Comparator, class Handler>
        CallbackCursor<Comparator, Handler> cursor(const DBTxn &txn, Comparator &&cmp, Handler &&handler) const;

        template<class Comparator, class Predicate>
        BufferedCursor<Comparator, Predicate> buffered_cursor(const DBTxn &txn, Comparator &&cmp, Predicate &&filter) const;

        template<class Comparator>
        SimpleCursor<Comparator> simple_cursor(const DBTxn &txn, Comparator &&cmp, Slice &key, Slice &val) const;

    private:
        DB_ENV *_env;
        bool _close_on_destroy;
    };

    class DBEnvBuilder {
        typedef int (*bt_compare_func)(DB *, const DBT *, const DBT *);
        bt_compare_func _bt_compare;

        typedef int (*update_func)(DB *, const DBT *, const DBT *, const DBT *, void (*)(const DBT *, void *), void *);
        update_func _update_function;

        generate_row_for_put_func _generate_row_for_put;
        generate_row_for_del_func _generate_row_for_del;

        uint32_t _cleaner_period;
        uint32_t _cleaner_iterations;
        uint32_t _checkpointing_period;
        uint32_t _fsync_log_period_msec;
        int _fs_redzone;

        uint64_t _lk_max_memory;
        uint64_t _lock_wait_time_msec;

        typedef uint64_t (*get_lock_wait_time_cb_func)(uint64_t);
        get_lock_wait_time_cb_func _get_lock_wait_time_cb;
        lock_timeout_callback _lock_timeout_callback;
        uint64_t (*_loader_memory_size_callback)(void);

        uint32_t _cachesize_gbytes;
        uint32_t _cachesize_bytes;
        uint32_t _cachetable_bucket_mutexes;

        std::string _product_name;

        std::string _lg_dir;
        std::string _tmp_dir;

        bool _direct_io;
        bool _compress_buffers;

    public:
        DBEnvBuilder()
            : _bt_compare(nullptr),
              _update_function(nullptr),
              _generate_row_for_put(nullptr),
              _generate_row_for_del(nullptr),
              _cleaner_period(0),
              _cleaner_iterations(0),
              _checkpointing_period(0),
              _fsync_log_period_msec(0),
              _fs_redzone(0),
              _lk_max_memory(0),
              _lock_wait_time_msec(0),
              _get_lock_wait_time_cb(nullptr),
              _lock_timeout_callback(nullptr),
              _loader_memory_size_callback(nullptr),
              _cachesize_gbytes(0),
              _cachesize_bytes(0),
              _cachetable_bucket_mutexes(0),
              _product_name(""),
              _lg_dir(""),
              _tmp_dir(""),
              _direct_io(false),
              _compress_buffers(true)
        {}

        DBEnv open(const char *env_dir, uint32_t flags, int mode) const {
            db_env_set_direct_io(_direct_io);
            db_env_set_compress_buffers_before_eviction(_compress_buffers);
            if (_cachetable_bucket_mutexes) {
                db_env_set_num_bucket_mutexes(_cachetable_bucket_mutexes);
            }

            if (!_product_name.empty()) {
                db_env_set_toku_product_name(_product_name.c_str());
            }

            DB_ENV *env;
            int r = db_env_create(&env, 0);
            handle_ft_retval(r);

            if (_bt_compare) {
                r = env->set_default_bt_compare(env, _bt_compare);
                handle_ft_retval(r);
            }

            if (_update_function) {
                env->set_update(env, _update_function);
            }

            if (_generate_row_for_put) {
                r = env->set_generate_row_callback_for_put(env, _generate_row_for_put);
                handle_ft_retval(r);
            }

            if (_generate_row_for_del) {
                r = env->set_generate_row_callback_for_del(env, _generate_row_for_del);
                handle_ft_retval(r);
            }

            if (_lk_max_memory) {
                r = env->set_lk_max_memory(env, _lk_max_memory);
                handle_ft_retval(r);
            }

            if (_lock_wait_time_msec || _get_lock_wait_time_cb) {
                uint64_t wait_time = _lock_wait_time_msec;
                if (!wait_time) {
                    r = env->get_lock_timeout(env, &wait_time);
                    handle_ft_retval(r);
                }
                r = env->set_lock_timeout(env, wait_time, _get_lock_wait_time_cb);
                handle_ft_retval(r);
            }

            if (_lock_timeout_callback) {
                r = env->set_lock_timeout_callback(env, _lock_timeout_callback);
                handle_ft_retval(r);
            }

            if (_loader_memory_size_callback) {
                env->set_loader_memory_size(env, _loader_memory_size_callback);
            }

            if (_cachesize_gbytes || _cachesize_bytes) {
                r = env->set_cachesize(env, _cachesize_gbytes, _cachesize_bytes, 1);
                handle_ft_retval(r);
            }

            if (_fs_redzone) {
                env->set_redzone(env, _fs_redzone);
            }

            if (!_lg_dir.empty()) {
                r = env->set_lg_dir(env, _lg_dir.c_str());
                handle_ft_retval(r);
            }

            if (!_tmp_dir.empty()) {
                r = env->set_tmp_dir(env, _tmp_dir.c_str());
                handle_ft_retval(r);
            }

            r = env->open(env, env_dir, flags, mode);
            handle_ft_retval(r);

            if (_cleaner_period) {
                r = env->cleaner_set_period(env, _cleaner_period);
                handle_ft_retval(r);
            }

            if (_cleaner_iterations) {
                r = env->cleaner_set_iterations(env, _cleaner_iterations);
                handle_ft_retval(r);
            }

            if (_checkpointing_period) {
                r = env->checkpointing_set_period(env, _checkpointing_period);
                handle_ft_retval(r);
            }

            if (_fsync_log_period_msec) {
                env->change_fsync_log_period(env, _fsync_log_period_msec);
            }

            return DBEnv(env, true);
        }

        DBEnvBuilder& set_direct_io(bool direct_io) {
            _direct_io = direct_io;
            return *this;
        }

        DBEnvBuilder& set_compress_buffers_before_eviction(bool compress_buffers) {
            _compress_buffers = compress_buffers;
            return *this;
        }

        DBEnvBuilder& set_default_bt_compare(bt_compare_func bt_compare) {
            _bt_compare = bt_compare;
            return *this;
        }

        DBEnvBuilder& set_update(update_func update_function) {
            _update_function = update_function;
            return *this;
        }

        DBEnvBuilder& set_generate_row_callback_for_put(generate_row_for_put_func generate_row_for_put) {
            _generate_row_for_put = generate_row_for_put;
            return *this;
        }

        DBEnvBuilder& set_generate_row_callback_for_del(generate_row_for_del_func generate_row_for_del) {
            _generate_row_for_del = generate_row_for_del;
            return *this;
        }

        DBEnvBuilder& cleaner_set_period(uint32_t period) {
            _cleaner_period = period;
            return *this;
        }

        DBEnvBuilder& cleaner_set_iterations(uint32_t iterations) {
            _cleaner_iterations = iterations;
            return *this;
        }

        DBEnvBuilder& checkpointing_set_period(uint32_t period) {
            _checkpointing_period = period;
            return *this;
        }

        DBEnvBuilder& change_fsync_log_period(uint32_t period) {
            _fsync_log_period_msec = period;
            return *this;
        }

        DBEnvBuilder& set_fs_redzone(int fs_redzone) {
            _fs_redzone = fs_redzone;
            return *this;
        }

        DBEnvBuilder& set_lk_max_memory(uint64_t sz) {
            _lk_max_memory = sz;
            return *this;
        }

        DBEnvBuilder& set_lock_wait_time_msec(uint64_t lock_wait_time_msec) {
            _lock_wait_time_msec = lock_wait_time_msec;
            return *this;
        }

        DBEnvBuilder& set_lock_wait_time_cb(get_lock_wait_time_cb_func get_lock_wait_time_cb) {
            _get_lock_wait_time_cb = get_lock_wait_time_cb;
            return *this;
        }

        DBEnvBuilder& set_lock_timeout_callback(lock_timeout_callback callback) {
            _lock_timeout_callback = callback;
            return *this;
        }

        DBEnvBuilder& set_loader_memory_size(uint64_t (*callback)(void)) {
            _loader_memory_size_callback = callback;
            return *this;
        }

        DBEnvBuilder& set_cachesize(uint32_t gbytes, uint32_t bytes) {
            _cachesize_gbytes = gbytes;
            _cachesize_bytes = bytes;
            return *this;
        }

        DBEnvBuilder& set_cachetable_bucket_mutexes(uint32_t mutexes) {
            _cachetable_bucket_mutexes = mutexes;
            return *this;
        }

        DBEnvBuilder& set_product_name(const char *product_name) {
            _product_name = std::string(product_name);
            return *this;
        }

        DBEnvBuilder& set_lg_dir(const char *lg_dir) {
            _lg_dir = std::string(lg_dir);
            return *this;
        }

        DBEnvBuilder& set_tmp_dir(const char *tmp_dir) {
            _tmp_dir = std::string(tmp_dir);
            return *this;
        }
    };

} // namespace ftcxx
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: smplmailsuppl.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 01:48:47 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_shell.hxx"

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#ifndef _SMPLMAILSUPPL_HXX_
#include "smplmailsuppl.hxx"
#endif

#ifndef _SMPLMAILCLIENT_HXX_
#include "smplmailclient.hxx"
#endif

using com::sun::star::uno::Reference;
using com::sun::star::uno::RuntimeException;
using com::sun::star::uno::Sequence;
using com::sun::star::lang::XServiceInfo;
using com::sun::star::system::XSimpleMailClientSupplier;
using com::sun::star::system::XSimpleMailClient;
using rtl::OUString;
using osl::Mutex;

using namespace cppu;

#define COMP_IMPL_NAME  "com.sun.star.sys.shell.SimpleSystemMail"

namespace // private
{
    Sequence< OUString > SAL_CALL Component_getSupportedServiceNames()
    {
        Sequence< OUString > aRet(1);
        aRet[0] = OUString::createFromAscii("com.sun.star.sys.shell.SimpleSystemMail");
        return aRet;
    }

} // end private namespace

CSmplMailSuppl::CSmplMailSuppl() :
    WeakComponentImplHelper2<XSimpleMailClientSupplier, XServiceInfo>(m_aMutex)
{
}

CSmplMailSuppl::~CSmplMailSuppl()
{
}

Reference<XSimpleMailClient> SAL_CALL CSmplMailSuppl::querySimpleMailClient()
    throw (RuntimeException)
{
    /* We just try to load the MAPI dll as a test
       if a mail client is available */
    Reference<XSimpleMailClient> xSmplMailClient;
    HMODULE handle = LoadLibrary("mapi32.dll");
    if ((handle != INVALID_HANDLE_VALUE) && (handle != NULL))
    {
        FreeLibrary(handle);
        xSmplMailClient = Reference<XSimpleMailClient>(new CSmplMailClient());
    }
    return xSmplMailClient;
}

// XServiceInfo

OUString SAL_CALL CSmplMailSuppl::getImplementationName()
    throw(RuntimeException)
{
    return OUString::createFromAscii(COMP_IMPL_NAME);
}

sal_Bool SAL_CALL CSmplMailSuppl::supportsService(const OUString& ServiceName)
    throw(RuntimeException)
{
    Sequence <OUString> SupportedServicesNames = Component_getSupportedServiceNames();

    for (sal_Int32 n = SupportedServicesNames.getLength(); n--;)
        if (SupportedServicesNames[n].compareTo(ServiceName) == 0)
            return sal_True;

    return sal_False;
}

Sequence<OUString> SAL_CALL CSmplMailSuppl::getSupportedServiceNames()
    throw(RuntimeException)
{
    return Component_getSupportedServiceNames();
}

<commit_msg>INTEGRATION: CWS changefileheader (1.5.122); FILE MERGED 2008/04/01 15:40:28 thb 1.5.122.3: #i85898# Stripping all external header guards 2008/04/01 12:41:17 thb 1.5.122.2: #i85898# Stripping all external header guards 2008/03/31 13:17:14 rt 1.5.122.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: smplmailsuppl.cxx,v $
 * $Revision: 1.6 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_shell.hxx"
#include <osl/diagnose.h>
#include "smplmailsuppl.hxx"
#include "smplmailclient.hxx"

using com::sun::star::uno::Reference;
using com::sun::star::uno::RuntimeException;
using com::sun::star::uno::Sequence;
using com::sun::star::lang::XServiceInfo;
using com::sun::star::system::XSimpleMailClientSupplier;
using com::sun::star::system::XSimpleMailClient;
using rtl::OUString;
using osl::Mutex;

using namespace cppu;

#define COMP_IMPL_NAME  "com.sun.star.sys.shell.SimpleSystemMail"

namespace // private
{
    Sequence< OUString > SAL_CALL Component_getSupportedServiceNames()
    {
        Sequence< OUString > aRet(1);
        aRet[0] = OUString::createFromAscii("com.sun.star.sys.shell.SimpleSystemMail");
        return aRet;
    }

} // end private namespace

CSmplMailSuppl::CSmplMailSuppl() :
    WeakComponentImplHelper2<XSimpleMailClientSupplier, XServiceInfo>(m_aMutex)
{
}

CSmplMailSuppl::~CSmplMailSuppl()
{
}

Reference<XSimpleMailClient> SAL_CALL CSmplMailSuppl::querySimpleMailClient()
    throw (RuntimeException)
{
    /* We just try to load the MAPI dll as a test
       if a mail client is available */
    Reference<XSimpleMailClient> xSmplMailClient;
    HMODULE handle = LoadLibrary("mapi32.dll");
    if ((handle != INVALID_HANDLE_VALUE) && (handle != NULL))
    {
        FreeLibrary(handle);
        xSmplMailClient = Reference<XSimpleMailClient>(new CSmplMailClient());
    }
    return xSmplMailClient;
}

// XServiceInfo

OUString SAL_CALL CSmplMailSuppl::getImplementationName()
    throw(RuntimeException)
{
    return OUString::createFromAscii(COMP_IMPL_NAME);
}

sal_Bool SAL_CALL CSmplMailSuppl::supportsService(const OUString& ServiceName)
    throw(RuntimeException)
{
    Sequence <OUString> SupportedServicesNames = Component_getSupportedServiceNames();

    for (sal_Int32 n = SupportedServicesNames.getLength(); n--;)
        if (SupportedServicesNames[n].compareTo(ServiceName) == 0)
            return sal_True;

    return sal_False;
}

Sequence<OUString> SAL_CALL CSmplMailSuppl::getSupportedServiceNames()
    throw(RuntimeException)
{
    return Component_getSupportedServiceNames();
}

<|endoftext|>


<commit_before>#include "graphics/gl.h"
#include "graphics/shader.h"

namespace demoloop {
  GL::GL()
    : maxAnisotropy(1.0f)
    , maxTextureSize(0)
    , maxRenderTargets(1)
    , maxRenderbufferSamples(0)
    , maxTextureUnits(1)
    , state()
  {
    initMatrices();
  }

  GL::~GL() {}

  bool GL::initContext() {
#ifndef EMSCRIPTEN
    glEnable(GL_MULTISAMPLE); // TODO: is this doing anything?
#endif
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);
    glEnable(GL_BLEND);

    initMaxValues();

    Shader::defaultShader = new Shader();
    Shader::defaultShader->attach();

    glGenBuffers(1, &mVBO);
    glGenBuffers(1, &mIBO);

    state.boundTextures.clear();
    state.boundTextures.resize(maxTextureUnits, 0);

    for (int i = 0; i < (int) state.boundTextures.size(); i++)
    {
      glActiveTexture(GL_TEXTURE0 + i);
      glBindTexture(GL_TEXTURE_2D, 0);
    }

    glActiveTexture(GL_TEXTURE0);
    state.curTextureUnit = 0;

    createDefaultTexture();

    glBindTexture(GL_TEXTURE_2D, state.defaultTexture);
    glVertexAttrib4f(ATTRIB_CONSTANTCOLOR, 1, 1, 1, 1);
    glVertexAttrib4f(ATTRIB_COLOR, 1, 1, 1, 1);

    GLint maxvertexattribs = 1;
    glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxvertexattribs);
    state.enabledAttribArrays = (uint32_t) ((1ull << uint32_t(maxvertexattribs)) - 1);
    useVertexAttribArrays(0);

    return true;
  }

  void GL::initMatrices() {
    matrices.transform.clear();
    matrices.projection.clear();

    matrices.transform.push_back(glm::mat4());
    matrices.projection.push_back(glm::mat4());
  }

  void GL::initMaxValues()
  {
    // We'll need this value to clamp anisotropy.
    if (GLEW_EXT_texture_filter_anisotropic)
      glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy);
    else
      maxAnisotropy = 1.0f;

    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);

    int maxattachments = 1;
    int maxdrawbuffers = 1;

    if (GLEW_VERSION_2_0)
    {
      glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxattachments);
      glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxdrawbuffers);
    }

    maxRenderTargets = std::min(maxattachments, maxdrawbuffers);

    if (GLEW_VERSION_3_0 || GLEW_ARB_framebuffer_object
      || GLEW_EXT_framebuffer_multisample || GLEW_ANGLE_framebuffer_multisample)
    {
      glGetIntegerv(GL_MAX_SAMPLES, &maxRenderbufferSamples);
    }
    else
      maxRenderbufferSamples = 0;

    glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
  }

  void GL::setViewport(const GL::Viewport &v) {
    glViewport(v.x, v.y, v.w, v.h);
    state.viewport = v;
    GLfloat dimensions[4] = {(GLfloat)v.w, (GLfloat)v.h, 0, 0};
    Shader::current->sendFloat("demoloop_ScreenSize", 4, dimensions, 1);
  }

  GL::Viewport GL::getViewport() const
  {
    return state.viewport;
  }

  void GL::pushTransform()
  {
    matrices.transform.push_back(matrices.transform.back());
  }

  void GL::popTransform()
  {
    matrices.transform.pop_back();
  }

  glm::mat4 &GL::getTransform()
  {
    return matrices.transform.back();
  }

  void GL::pushProjection()
  {
    matrices.projection.push_back(matrices.projection.back());
  }

  void GL::popProjection()
  {
    matrices.projection.pop_back();
  }

  glm::mat4 &GL::getProjection()
  {
    return matrices.projection.back();
  }

  void GL::useVertexAttribArrays(uint32_t arraybits)
  {
    uint32_t diff = arraybits ^ state.enabledAttribArrays;

    if (diff == 0)
      return;

    // Max 32 attributes. As of when this was written, no GL driver exposes more
    // than 32. Lets hope that doesn't change...
    for (uint32_t i = 0; i < 32; i++)
    {
      uint32_t bit = 1 << i;

      if (diff & bit)
      {
        if (arraybits & bit)
          glEnableVertexAttribArray(i);
        else
          glDisableVertexAttribArray(i);
      }
    }

    state.enabledAttribArrays = arraybits;

    // glDisableVertexAttribArray will make the constant value for a vertex
    // attribute undefined. We rely on the per-vertex color attribute being
    // white when no per-vertex color is used, so we set it here.
    // FIXME: Is there a better place to do this?
    if ((diff & ATTRIBFLAG_COLOR) && !(arraybits & ATTRIBFLAG_COLOR))
      glVertexAttrib4f(ATTRIB_COLOR, 1.0f, 1.0f, 1.0f, 1.0f);
  }

  GLint GL::getGLWrapMode(Texture::WrapMode wmode)
  {
    switch (wmode)
    {
    case Texture::WRAP_CLAMP:
    default:
      return GL_CLAMP_TO_EDGE;
    case Texture::WRAP_CLAMP_ZERO:
      return GL_CLAMP_TO_BORDER;
    case Texture::WRAP_REPEAT:
      return GL_REPEAT;
    case Texture::WRAP_MIRRORED_REPEAT:
      return GL_MIRRORED_REPEAT;
    }

  }

  void GL::drawArrays(GLenum mode, GLint first, GLsizei count)
  {
    glDrawArrays(mode, first, count);
    // ++stats.drawCalls;
  }

  void GL::drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
  {
    glDrawArraysInstanced(mode, first, count, primcount);
    // ++stats.drawCalls;
  }

  void GL::drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices)
  {
    glDrawElements(mode, count, type, indices);
    // ++stats.drawCalls;
  }

  void GL::deleteTexture(GLuint texture)
  {
    // glDeleteTextures binds texture 0 to all texture units the deleted texture
    // was bound to before deletion.
    for (GLuint &texid : state.boundTextures)
    {
      if (texid == texture)
        texid = 0;
    }

    glDeleteTextures(1, &texture);
  }

  void GL::setTextureWrap(const Texture::Wrap &w)
  {
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, getGLWrapMode(w.s));
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, getGLWrapMode(w.t));
  }

  void GL::bindFramebuffer(GLenum target, GLuint framebuffer) {
    glBindFramebuffer(target, framebuffer);
  }

  void GL::setTextureFilter(Texture::Filter &f)
  {
    GLint gmin, gmag;

    if (f.mipmap == Texture::FILTER_NONE)
    {
      if (f.min == Texture::FILTER_NEAREST)
        gmin = GL_NEAREST;
      else // f.min == Texture::FILTER_LINEAR
        gmin = GL_LINEAR;
    }
    else
    {
      if (f.min == Texture::FILTER_NEAREST && f.mipmap == Texture::FILTER_NEAREST)
        gmin = GL_NEAREST_MIPMAP_NEAREST;
      else if (f.min == Texture::FILTER_NEAREST && f.mipmap == Texture::FILTER_LINEAR)
        gmin = GL_NEAREST_MIPMAP_LINEAR;
      else if (f.min == Texture::FILTER_LINEAR && f.mipmap == Texture::FILTER_NEAREST)
        gmin = GL_LINEAR_MIPMAP_NEAREST;
      else if (f.min == Texture::FILTER_LINEAR && f.mipmap == Texture::FILTER_LINEAR)
        gmin = GL_LINEAR_MIPMAP_LINEAR;
      else
        gmin = GL_LINEAR;
    }

    switch (f.mag)
    {
    case Texture::FILTER_NEAREST:
      gmag = GL_NEAREST;
      break;
    case Texture::FILTER_LINEAR:
    default:
      gmag = GL_LINEAR;
      break;
    }

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gmin);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gmag);

    // if (GLAD_EXT_texture_filter_anisotropic)
    // {
    //   f.anisotropy = std::min(std::max(f.anisotropy, 1.0f), maxAnisotropy);
    //   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, f.anisotropy);
    // }
    // else
      f.anisotropy = 1.0f;
  }

  void GL::bindTexture(GLuint texture)
  {
    if (texture != state.boundTextures[state.curTextureUnit])
    {
      state.boundTextures[state.curTextureUnit] = texture;
      glBindTexture(GL_TEXTURE_2D, texture);
    }
  }

  void GL::prepareDraw() {
    glm::mat4 modelView;
    prepareDraw(modelView);
  }

  void GL::prepareDraw(glm::mat4 modelView) {
    Shader::current->checkSetBuiltinUniforms(modelView);
  }

  void GL::bufferVertices(const Vertex *vertices, size_t count, GLenum usage) {
    glBindBuffer(GL_ARRAY_BUFFER, mVBO);
    glBufferData(GL_ARRAY_BUFFER, count * sizeof(Vertex), &vertices[0].x, usage);
  }

  void GL::lines(const Vertex *coords, size_t count) {
    prepareDraw();

    glBindBuffer(GL_ARRAY_BUFFER, mVBO);
    glBufferData(GL_ARRAY_BUFFER, count * sizeof(Vertex), &coords[0].x, GL_DYNAMIC_DRAW);

    useVertexAttribArrays(ATTRIBFLAG_POS | ATTRIBFLAG_COLOR);

    glVertexAttribPointer(ATTRIB_POS, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) offsetof(Vertex, x));
    glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (GLvoid*) offsetof(Vertex, r));

    glDrawArrays(GL_LINES, 0, count);
  }

  void GL::triangles(const Vertex *coords, size_t count) {
    prepareDraw();

    glBindBuffer(GL_ARRAY_BUFFER, mVBO);
    glBufferData(GL_ARRAY_BUFFER, count * sizeof(Vertex), &coords[0].x, GL_DYNAMIC_DRAW);

    useVertexAttribArrays(ATTRIBFLAG_POS | ATTRIBFLAG_COLOR | ATTRIBFLAG_TEXCOORD);

    glVertexAttribPointer(ATTRIB_POS, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) offsetof(Vertex, x));
    glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) offsetof(Vertex, s));
    glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (GLvoid*) offsetof(Vertex, r));

    glDrawArrays(GL_TRIANGLES, 0, count);
  }

  void GL::triangles(const Triangle *triangleVertices, size_t count) {
    triangles((Vertex *)triangleVertices, count * 3);
  }

  GLuint GL::getDefaultTexture() const {
    return state.defaultTexture;
  }

  void GL::createDefaultTexture()
  {
    // Set the 'default' texture (id 0) as a repeating white pixel. Otherwise,
    // texture2D calls inside a shader would return black when drawing graphics
    // primitives, which would create the need to use different "passthrough"
    // shaders for untextured primitives vs images.

    GLuint curtexture = state.boundTextures[state.curTextureUnit];

    glGenTextures(1, &state.defaultTexture);
    glBindTexture(GL_TEXTURE_2D, state.defaultTexture);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

    GLubyte pix[] = {255, 255, 255, 255};
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, pix);

    bindTexture(curtexture);
  }

  GL gl;
}
<commit_msg>clean up default buffers and textures<commit_after>#include "graphics/gl.h"
#include "graphics/shader.h"

namespace demoloop {
  GL::GL()
    : maxAnisotropy(1.0f)
    , maxTextureSize(0)
    , maxRenderTargets(1)
    , maxRenderbufferSamples(0)
    , maxTextureUnits(1)
    , state()
  {
    initMatrices();
  }

  GL::~GL() {
    glDeleteBuffers(1, &mVBO);
    glDeleteBuffers(1, &mIBO);

    deleteTexture(state.defaultTexture);
  }

  bool GL::initContext() {
#ifndef EMSCRIPTEN
    glEnable(GL_MULTISAMPLE); // TODO: is this doing anything?
#endif
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);
    glEnable(GL_BLEND);

    initMaxValues();

    Shader::defaultShader = new Shader();
    Shader::defaultShader->attach();

    glGenBuffers(1, &mVBO);
    glGenBuffers(1, &mIBO);

    state.boundTextures.clear();
    state.boundTextures.resize(maxTextureUnits, 0);

    for (int i = 0; i < (int) state.boundTextures.size(); i++)
    {
      glActiveTexture(GL_TEXTURE0 + i);
      glBindTexture(GL_TEXTURE_2D, 0);
    }

    glActiveTexture(GL_TEXTURE0);
    state.curTextureUnit = 0;

    createDefaultTexture();

    glBindTexture(GL_TEXTURE_2D, state.defaultTexture);
    glVertexAttrib4f(ATTRIB_CONSTANTCOLOR, 1, 1, 1, 1);
    glVertexAttrib4f(ATTRIB_COLOR, 1, 1, 1, 1);

    GLint maxvertexattribs = 1;
    glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxvertexattribs);
    state.enabledAttribArrays = (uint32_t) ((1ull << uint32_t(maxvertexattribs)) - 1);
    useVertexAttribArrays(0);

    return true;
  }

  void GL::initMatrices() {
    matrices.transform.clear();
    matrices.projection.clear();

    matrices.transform.push_back(glm::mat4());
    matrices.projection.push_back(glm::mat4());
  }

  void GL::initMaxValues()
  {
    // We'll need this value to clamp anisotropy.
    if (GLEW_EXT_texture_filter_anisotropic)
      glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy);
    else
      maxAnisotropy = 1.0f;

    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);

    int maxattachments = 1;
    int maxdrawbuffers = 1;

    if (GLEW_VERSION_2_0)
    {
      glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxattachments);
      glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxdrawbuffers);
    }

    maxRenderTargets = std::min(maxattachments, maxdrawbuffers);

    if (GLEW_VERSION_3_0 || GLEW_ARB_framebuffer_object
      || GLEW_EXT_framebuffer_multisample || GLEW_ANGLE_framebuffer_multisample)
    {
      glGetIntegerv(GL_MAX_SAMPLES, &maxRenderbufferSamples);
    }
    else
      maxRenderbufferSamples = 0;

    glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
  }

  void GL::setViewport(const GL::Viewport &v) {
    glViewport(v.x, v.y, v.w, v.h);
    state.viewport = v;
    GLfloat dimensions[4] = {(GLfloat)v.w, (GLfloat)v.h, 0, 0};
    Shader::current->sendFloat("demoloop_ScreenSize", 4, dimensions, 1);
  }

  GL::Viewport GL::getViewport() const
  {
    return state.viewport;
  }

  void GL::pushTransform()
  {
    matrices.transform.push_back(matrices.transform.back());
  }

  void GL::popTransform()
  {
    matrices.transform.pop_back();
  }

  glm::mat4 &GL::getTransform()
  {
    return matrices.transform.back();
  }

  void GL::pushProjection()
  {
    matrices.projection.push_back(matrices.projection.back());
  }

  void GL::popProjection()
  {
    matrices.projection.pop_back();
  }

  glm::mat4 &GL::getProjection()
  {
    return matrices.projection.back();
  }

  void GL::useVertexAttribArrays(uint32_t arraybits)
  {
    uint32_t diff = arraybits ^ state.enabledAttribArrays;

    if (diff == 0)
      return;

    // Max 32 attributes. As of when this was written, no GL driver exposes more
    // than 32. Lets hope that doesn't change...
    for (uint32_t i = 0; i < 32; i++)
    {
      uint32_t bit = 1 << i;

      if (diff & bit)
      {
        if (arraybits & bit)
          glEnableVertexAttribArray(i);
        else
          glDisableVertexAttribArray(i);
      }
    }

    state.enabledAttribArrays = arraybits;

    // glDisableVertexAttribArray will make the constant value for a vertex
    // attribute undefined. We rely on the per-vertex color attribute being
    // white when no per-vertex color is used, so we set it here.
    // FIXME: Is there a better place to do this?
    if ((diff & ATTRIBFLAG_COLOR) && !(arraybits & ATTRIBFLAG_COLOR))
      glVertexAttrib4f(ATTRIB_COLOR, 1.0f, 1.0f, 1.0f, 1.0f);
  }

  GLint GL::getGLWrapMode(Texture::WrapMode wmode)
  {
    switch (wmode)
    {
    case Texture::WRAP_CLAMP:
    default:
      return GL_CLAMP_TO_EDGE;
    case Texture::WRAP_CLAMP_ZERO:
      return GL_CLAMP_TO_BORDER;
    case Texture::WRAP_REPEAT:
      return GL_REPEAT;
    case Texture::WRAP_MIRRORED_REPEAT:
      return GL_MIRRORED_REPEAT;
    }

  }

  void GL::drawArrays(GLenum mode, GLint first, GLsizei count)
  {
    glDrawArrays(mode, first, count);
    // ++stats.drawCalls;
  }

  void GL::drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
  {
    glDrawArraysInstanced(mode, first, count, primcount);
    // ++stats.drawCalls;
  }

  void GL::drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices)
  {
    glDrawElements(mode, count, type, indices);
    // ++stats.drawCalls;
  }

  void GL::deleteTexture(GLuint texture)
  {
    // glDeleteTextures binds texture 0 to all texture units the deleted texture
    // was bound to before deletion.
    for (GLuint &texid : state.boundTextures)
    {
      if (texid == texture)
        texid = 0;
    }

    glDeleteTextures(1, &texture);
  }

  void GL::setTextureWrap(const Texture::Wrap &w)
  {
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, getGLWrapMode(w.s));
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, getGLWrapMode(w.t));
  }

  void GL::bindFramebuffer(GLenum target, GLuint framebuffer) {
    glBindFramebuffer(target, framebuffer);
  }

  void GL::setTextureFilter(Texture::Filter &f)
  {
    GLint gmin, gmag;

    if (f.mipmap == Texture::FILTER_NONE)
    {
      if (f.min == Texture::FILTER_NEAREST)
        gmin = GL_NEAREST;
      else // f.min == Texture::FILTER_LINEAR
        gmin = GL_LINEAR;
    }
    else
    {
      if (f.min == Texture::FILTER_NEAREST && f.mipmap == Texture::FILTER_NEAREST)
        gmin = GL_NEAREST_MIPMAP_NEAREST;
      else if (f.min == Texture::FILTER_NEAREST && f.mipmap == Texture::FILTER_LINEAR)
        gmin = GL_NEAREST_MIPMAP_LINEAR;
      else if (f.min == Texture::FILTER_LINEAR && f.mipmap == Texture::FILTER_NEAREST)
        gmin = GL_LINEAR_MIPMAP_NEAREST;
      else if (f.min == Texture::FILTER_LINEAR && f.mipmap == Texture::FILTER_LINEAR)
        gmin = GL_LINEAR_MIPMAP_LINEAR;
      else
        gmin = GL_LINEAR;
    }

    switch (f.mag)
    {
    case Texture::FILTER_NEAREST:
      gmag = GL_NEAREST;
      break;
    case Texture::FILTER_LINEAR:
    default:
      gmag = GL_LINEAR;
      break;
    }

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gmin);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gmag);

    // if (GLAD_EXT_texture_filter_anisotropic)
    // {
    //   f.anisotropy = std::min(std::max(f.anisotropy, 1.0f), maxAnisotropy);
    //   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, f.anisotropy);
    // }
    // else
      f.anisotropy = 1.0f;
  }

  void GL::bindTexture(GLuint texture)
  {
    if (texture != state.boundTextures[state.curTextureUnit])
    {
      state.boundTextures[state.curTextureUnit] = texture;
      glBindTexture(GL_TEXTURE_2D, texture);
    }
  }

  void GL::prepareDraw() {
    glm::mat4 modelView;
    prepareDraw(modelView);
  }

  void GL::prepareDraw(glm::mat4 modelView) {
    Shader::current->checkSetBuiltinUniforms(modelView);
  }

  void GL::bufferVertices(const Vertex *vertices, size_t count, GLenum usage) {
    glBindBuffer(GL_ARRAY_BUFFER, mVBO);
    glBufferData(GL_ARRAY_BUFFER, count * sizeof(Vertex), &vertices[0].x, usage);
  }

  void GL::lines(const Vertex *coords, size_t count) {
    prepareDraw();

    glBindBuffer(GL_ARRAY_BUFFER, mVBO);
    glBufferData(GL_ARRAY_BUFFER, count * sizeof(Vertex), &coords[0].x, GL_DYNAMIC_DRAW);

    useVertexAttribArrays(ATTRIBFLAG_POS | ATTRIBFLAG_COLOR);

    glVertexAttribPointer(ATTRIB_POS, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) offsetof(Vertex, x));
    glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (GLvoid*) offsetof(Vertex, r));

    glDrawArrays(GL_LINES, 0, count);
  }

  void GL::triangles(const Vertex *coords, size_t count) {
    prepareDraw();

    glBindBuffer(GL_ARRAY_BUFFER, mVBO);
    glBufferData(GL_ARRAY_BUFFER, count * sizeof(Vertex), &coords[0].x, GL_DYNAMIC_DRAW);

    useVertexAttribArrays(ATTRIBFLAG_POS | ATTRIBFLAG_COLOR | ATTRIBFLAG_TEXCOORD);

    glVertexAttribPointer(ATTRIB_POS, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) offsetof(Vertex, x));
    glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) offsetof(Vertex, s));
    glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (GLvoid*) offsetof(Vertex, r));

    glDrawArrays(GL_TRIANGLES, 0, count);
  }

  void GL::triangles(const Triangle *triangleVertices, size_t count) {
    triangles((Vertex *)triangleVertices, count * 3);
  }

  GLuint GL::getDefaultTexture() const {
    return state.defaultTexture;
  }

  void GL::createDefaultTexture()
  {
    // Set the 'default' texture (id 0) as a repeating white pixel. Otherwise,
    // texture2D calls inside a shader would return black when drawing graphics
    // primitives, which would create the need to use different "passthrough"
    // shaders for untextured primitives vs images.

    GLuint curtexture = state.boundTextures[state.curTextureUnit];

    glGenTextures(1, &state.defaultTexture);
    glBindTexture(GL_TEXTURE_2D, state.defaultTexture);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

    GLubyte pix[] = {255, 255, 255, 255};
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, pix);

    bindTexture(curtexture);
  }

  GL gl;
}
<|endoftext|>


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

#include "RhoConvertWP8.h"
#include "common/StringConverter.h"
#include <collection.h>

using namespace Windows::Foundation::Collections;

namespace rho
{
namespace common
{

::Platform::String^ convertStringCToWP8(const char* str)
{
	rho::StringW strW;
	if (str)
		rho::common::convertToStringW(str, strW);
	return ref new Platform::String(strW.c_str());
}

::Platform::String^ convertStringToWP8(const String& str)
{
    rho::StringW strW = rho::common::convertToStringW(str);
    return ref new ::Platform::String(strW.c_str());
}

::Platform::String^ convertStringWToWP8(const StringW& str)
{
    return ref new ::Platform::String(str.c_str());
}

IVectorView<Platform::String^>^ convertArrayWP8(const Vector<String>& arr)
{
    // TODO: convert string array
    return ref new Platform::Collections::VectorView<Platform::String^>();
}

IMapView<Platform::String^, Platform::String^>^ convertHashWP8(const Hashtable<String, String>& hash)
{
    // TODO: convert string hash
    return ref new Platform::Collections::MapView<Platform::String^, Platform::String^>();
}

String convertStringAFromWP8(::Platform::String^ str)
{
    return rho::common::convertToStringA(str->Data());
}

StringW convertStringWFromWP8(::Platform::String^ str)
{
    return rho::common::convertToStringW(str->Data());
}

Vector<rho::String> convertArrayFromWP8(::Windows::Foundation::Collections::IVectorView<Platform::String^>^ arr)
{
    Vector<rho::String> vec;
    // TODO: convert string array from C#
    return vec;
}

Hashtable<rho::String, rho::String> convertHashFromWP8(::Windows::Foundation::Collections::IMapView<Platform::String^, Platform::String^>^ hash)
{
    Hashtable<rho::String, rho::String> ht;
    // TODO: convert string hash from C#
    return ht;
}

}
}
<commit_msg>wp8: rho::Vector and rho::Hashtable C#/C++ bi-directional conversion implemented<commit_after>/*------------------------------------------------------------------------
* (The MIT License)
*
* Copyright (c) 2008-2011 Rhomobile, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* http://rhomobile.com
*------------------------------------------------------------------------*/

#include "RhoConvertWP8.h"
#include "common/StringConverter.h"
#include <collection.h>

using namespace Windows::Foundation::Collections;

namespace rho
{
namespace common
{

::Platform::String^ convertStringCToWP8(const char* str)
{
	rho::StringW strW;
	if (str)
		rho::common::convertToStringW(str, strW);
	return ref new Platform::String(strW.c_str());
}

::Platform::String^ convertStringToWP8(const String& str)
{
    rho::StringW strW = rho::common::convertToStringW(str);
    return ref new ::Platform::String(strW.c_str());
}

::Platform::String^ convertStringWToWP8(const StringW& str)
{
    return ref new ::Platform::String(str.c_str());
}

IVectorView<Platform::String^>^ convertArrayWP8(const Vector<String>& arr)
{
	IVector<Platform::String^>^ res = ref new Platform::Collections::Vector<Platform::String^>();
	for (Vector<String>::const_iterator i = arr.begin(); i != arr.end(); ++i)
		res->Append(convertStringToWP8(*i));
	return res->GetView();
}

IMapView<Platform::String^, Platform::String^>^ convertHashWP8(const Hashtable<String, String>& hash)
{
	IMap<Platform::String^, Platform::String^>^ res = ref new Platform::Collections::Map<Platform::String^, Platform::String^>();
	for(Hashtable<String, String>::const_iterator i = hash.begin(); i != hash.end(); ++i)
		res->Insert(convertStringToWP8(i->first), convertStringToWP8(i->second));
	return res->GetView();
}

String convertStringAFromWP8(::Platform::String^ str)
{
    return rho::common::convertToStringA(str->Data());
}

StringW convertStringWFromWP8(::Platform::String^ str)
{
    return rho::common::convertToStringW(str->Data());
}

Vector<rho::String> convertArrayFromWP8(IVectorView<Platform::String^>^ arr)
{
    Vector<rho::String> vec;
	for (IIterator<Platform::String^>^ i = arr->First(); i->HasCurrent; i->MoveNext())
		vec.addElement(convertStringAFromWP8(i->Current));
    return vec;
}

Hashtable<rho::String, rho::String> convertHashFromWP8(IMapView<Platform::String^, Platform::String^>^ hash)
{
    Hashtable<rho::String, rho::String> ht;
	for (IIterator<IKeyValuePair<Platform::String^, Platform::String^>^>^ i = hash->First(); i->HasCurrent; i->MoveNext())
		ht.emplace(convertStringAFromWP8(i->Current->Key), convertStringAFromWP8(i->Current->Value));
    return ht;
}

}
}
<|endoftext|>