<commit_before>#include "texture.h"

#include "platform.h"
#include "util/geom.h"
#include "gl/renderState.h"

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

#include <cstring> // for memset

namespace Tangram {

int Texture::s_validGeneration = 0;

Texture::Texture(unsigned int _width, unsigned int _height, TextureOptions _options, bool _generateMipmaps)
    : m_options(_options), m_generateMipmaps(_generateMipmaps) {

    m_glHandle = 0;
    m_dirty = false;
    m_shouldResize = false;
    m_target = GL_TEXTURE_2D;
    m_generation = -1;

    resize(_width, _height);
}

Texture::Texture(const std::string& _file, TextureOptions _options, bool _generateMipmaps)
    : Texture(0, 0, _options, _generateMipmaps) {

    unsigned int size;
    unsigned char* data = bytesFromResource(_file.c_str(), &size);
    unsigned char* pixels;
    int width, height, comp;

    pixels = stbi_load_from_memory(data, size, &width, &height, &comp, STBI_rgb_alpha);

    resize(width, height);
    setData(reinterpret_cast<GLuint*>(pixels), width * height);
    update(0);

    free(data);
    stbi_image_free(pixels);
}

Texture::~Texture() {
    if (m_glHandle) {
        glDeleteTextures(1, &m_glHandle);

        // if the texture is bound, and deleted, the binding defaults to 0 according to the OpenGL
        // spec, in this case we need to force the currently bound texture to 0 in the render states
        if (RenderState::texture.compare(m_target, m_glHandle)) {
            RenderState::texture.init(m_target, 0, false);
        }
    }
}

void Texture::setData(const GLuint* _data, unsigned int _dataSize) {

    if (m_data.size() > 0) { m_data.clear(); }

    m_data.insert(m_data.begin(), _data, _data + _dataSize);

    m_dirty = true;
}

void Texture::setSubData(const GLuint* _subData, unsigned int _xoff, unsigned int _yoff, unsigned int _width,
                         unsigned int _height) {

    // update m_data with subdata
    size_t bpp = bytesPerPixel();
    size_t divisor = sizeof(GLuint) / bpp;
    for (size_t j = 0; j < _height; j++) {
        size_t dpos = ((j + _yoff) * m_width + _xoff) / divisor;
        size_t spos = (j * _width) / divisor;
        std::memcpy(&m_data[dpos], &_subData[spos], _width * bpp);
    }

    m_subData.push({{_subData, _subData + (_width * _height)}, _xoff, _yoff, _width, _height});

    m_dirty = true;
}

void Texture::bind(GLuint _unit) {
    RenderState::textureUnit(_unit);
    RenderState::texture(m_target, m_glHandle);
}

void Texture::generate(GLuint _textureUnit) {
    glGenTextures(1, &m_glHandle);

    bind(_textureUnit);

    if (m_generateMipmaps) {
        GLenum mipmapFlags = GL_LINEAR_MIPMAP_LINEAR | GL_LINEAR_MIPMAP_NEAREST | GL_NEAREST_MIPMAP_LINEAR | GL_NEAREST_MIPMAP_NEAREST;
        if (m_options.m_filtering.m_min & mipmapFlags) {
            logMsg("Warning: wrong options provided for the usage of mipmap generation\n");
        }
    }
<commit_msg>fix segv: read out of bounds<commit_after>#include "texture.h"

#include "platform.h"
#include "util/geom.h"
#include "gl/renderState.h"

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

#include <cstring> // for memset

namespace Tangram {

int Texture::s_validGeneration = 0;

Texture::Texture(unsigned int _width, unsigned int _height, TextureOptions _options, bool _generateMipmaps)
    : m_options(_options), m_generateMipmaps(_generateMipmaps) {

    m_glHandle = 0;
    m_dirty = false;
    m_shouldResize = false;
    m_target = GL_TEXTURE_2D;
    m_generation = -1;

    resize(_width, _height);
}

Texture::Texture(const std::string& _file, TextureOptions _options, bool _generateMipmaps)
    : Texture(0, 0, _options, _generateMipmaps) {

    unsigned int size;
    unsigned char* data = bytesFromResource(_file.c_str(), &size);
    unsigned char* pixels;
    int width, height, comp;

    pixels = stbi_load_from_memory(data, size, &width, &height, &comp, STBI_rgb_alpha);

    resize(width, height);
    setData(reinterpret_cast<GLuint*>(pixels), width * height);
    update(0);

    free(data);
    stbi_image_free(pixels);
}

Texture::~Texture() {
    if (m_glHandle) {
        glDeleteTextures(1, &m_glHandle);

        // if the texture is bound, and deleted, the binding defaults to 0 according to the OpenGL
        // spec, in this case we need to force the currently bound texture to 0 in the render states
        if (RenderState::texture.compare(m_target, m_glHandle)) {
            RenderState::texture.init(m_target, 0, false);
        }
    }
}

void Texture::setData(const GLuint* _data, unsigned int _dataSize) {

    if (m_data.size() > 0) { m_data.clear(); }

    m_data.insert(m_data.begin(), _data, _data + _dataSize);

    m_dirty = true;
}

void Texture::setSubData(const GLuint* _subData, unsigned int _xoff, unsigned int _yoff, unsigned int _width,
                         unsigned int _height) {

    // update m_data with subdata
    size_t bpp = bytesPerPixel();
    size_t divisor = sizeof(GLuint) / bpp;
    for (size_t j = 0; j < _height; j++) {
        size_t dpos = ((j + _yoff) * m_width + _xoff) / divisor;
        size_t spos = (j * _width) / divisor;
        std::memcpy(&m_data[dpos], &_subData[spos], _width * bpp);
    }

    m_subData.push_back({{_subData, _subData + (_width * _height) / divisor}, _xoff, _yoff, _width, _height});

    m_dirty = true;
}

void Texture::bind(GLuint _unit) {
    RenderState::textureUnit(_unit);
    RenderState::texture(m_target, m_glHandle);
}

void Texture::generate(GLuint _textureUnit) {
    glGenTextures(1, &m_glHandle);

    bind(_textureUnit);

    if (m_generateMipmaps) {
        GLenum mipmapFlags = GL_LINEAR_MIPMAP_LINEAR | GL_LINEAR_MIPMAP_NEAREST | GL_NEAREST_MIPMAP_LINEAR | GL_NEAREST_MIPMAP_NEAREST;
        if (m_options.m_filtering.m_min & mipmapFlags) {
            logMsg("Warning: wrong options provided for the usage of mipmap generation\n");
        }
    }

{'fraction_non_alphanumeric': 0.11546252532072923, 'fraction_numerical': 0.004726536124240378, 'mean_word_length': 3.561200923787529, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7450972', 'n_tokens_mistral': 2100, 'n_tokens_neox': 2042, 'n_words': 488}