<commit_before>#!/usr/bin/python
# $Id:$

import ctypes
import re

from pyglet.gl import *
from pyglet.gl import gl_info

_c_types = {
    GL_BYTE: ctypes.c_byte,
    GL_UNSIGNED_BYTE: ctypes.c_ubyte,
    GL_SHORT: ctypes.c_short,
    GL_UNSIGNED_SHORT: ctypes.c_ushort,
    GL_INT: ctypes.c_int,
    GL_UNSIGNED_INT: ctypes.c_uint,
    GL_FLOAT: ctypes.c_float,
    GL_DOUBLE: ctypes.c_double,
}

def create(size, target=GL_ARRAY_BUFFER, usage=GL_DYNAMIC_DRAW, 
           vbo=True, backed=False):
    '''Create a buffer of vertex data.
    '''
    if vbo and gl_info.have_version(1, 5):
        if backed:
            return BackedVertexBufferObject(size, target, usage)
        else:
            return VertexBufferObject(size, target, usage)
    else:
        return VertexArray(size)


class AbstractBuffer(object):
    #: Memory offset of buffer needed by glVertexPointer etc.
    ptr = 0
    #: Size of buffer, in bytes.
    size = 0

    def bind(self):
        raise NotImplementedError('abstract')

    def unbind(self):
        raise NotImplementedError('abstract')

    def set_data(self, data):
        raise NotImplementedError('abstract')

    def set_data_region(self, data, start, length):
        raise NotImplementedError('abstract')

    def map(self, invalidate=False):
        raise NotImplementedError('abstract')

    def unmap(self):
        raise NotImplementedError('abstract')

    def delete(self):
        raise NotImplementedError('abstract')

class VertexBufferObject(AbstractBuffer):
    def __init__(self, size, target, usage):
        self.size = size
        self.target = target
        self.usage = usage

        id = GLuint()
        glGenBuffers(1, id)
        self.id = id.value
        glBindBuffer(target, self.id)
        glBufferData(target, self.size, None, self.usage)

    def bind(self):
        glBindBuffer(self.target, self.id)

    def unbind(self):
        glBindBuffer(self.target, 0)

    def set_data(self, data):
        glBindBuffer(self.target, self.id)
        glBufferData(self.target, self.size, data, self.usage)

    def set_data_region(self, data, start, length):
        glBindBuffer(self.target, self.id)
        glBufferSubData(self.target, start, length, data)

    def map(self, invalidate=False):
        glBindBuffer(self.target, self.id)
        if invalidate:
            glBufferData(self.target, self.size, None, self.usage)
        return ctypes.cast(glMapBuffer(self.target, GL_WRITE_ONLY),
                           ctypes.POINTER(ctypes.c_byte * self.size)).contents

    def unmap(self):
        glUnmapBuffer(self.target)

    def delete(self):
        id = gl.GLuint(self.id)
        glDeleteBuffers(1, id)

    def resize(self, size):
        # Map, create a copy, then reinitialize.
        temp = (ctypes.c_byte * size)()

        glBindBuffer(self.target, self.id)
        data = glMapBuffer(self.target, GL_READ_ONLY)
        ctypes.memmove(temp, data, min(size, self.size))
        glUnmapBuffer(self.target)

        self.size = size
        glBufferData(self.target, self.size, temp, self.usage)

class BackedVertexBufferObject(VertexBufferObject):
    '''A VBO with system-memory backed store.
    
    Updates to the data via `set_data`, `set_data_region` and `map` will be
    held in local memory until `bind` is called.  The advantage is that fewer
    OpenGL calls are needed, increasing performance.  
    
    There may also be less performance penalty for resizing this buffer.

    Updates to data via `map` are committed immediately.
    '''
    def __init__(self, size, target, usage):
        super(BackedVertexBufferObject, self).__init__(size, target, usage)
        self.data = (ctypes.c_byte * size)()
        self.data_ptr = ctypes.cast(self.data, ctypes.c_void_p).value
        self._dirty = False

    def bind(self):
        # Commit pending data
        super(BackedVertexBufferObject, self).bind()
        if self._dirty:
            glBufferData(self.target, self.size, self.data, self.usage)
            self._dirty = False

    def set_data(self, data):
        super(VertexBufferObject, self).set_data(data)
        ctypes.memmove(self.data, data, self.size)
        self._dirty = True

    def set_data_region(self, data, start, length):
        ctypes.memmove(self.data_ptr + start, data, length)
        self._dirty = True

    def map(self, invalidate=False):
        self._dirty = True
        return self.data
        
    def unmap(self):
        pass

    def resize(self, size):
        data = (ctypes.c_byte * size)()
        ctypes.memmove(data, self.data, min(size, self.size))
        self.data = data
        self.data_ptr = ctypes.cast(self.data, ctypes.c_void_p).value
        
        self.size = size
        glBindBuffer(self.target, self.id)
        glBufferData(self.target, self.size, self.data, self.usage)


class VertexArray(AbstractBuffer):
    def __init__(self, size):
        self.size = size

        self.array = (ctypes.c_byte * size)()<commit_msg>Always restore buffer binding.<commit_after>#!/usr/bin/python
# $Id:$

import ctypes
import re

from pyglet.gl import *
from pyglet.gl import gl_info

_c_types = {
    GL_BYTE: ctypes.c_byte,
    GL_UNSIGNED_BYTE: ctypes.c_ubyte,
    GL_SHORT: ctypes.c_short,
    GL_UNSIGNED_SHORT: ctypes.c_ushort,
    GL_INT: ctypes.c_int,
    GL_UNSIGNED_INT: ctypes.c_uint,
    GL_FLOAT: ctypes.c_float,
    GL_DOUBLE: ctypes.c_double,
}

def create(size, target=GL_ARRAY_BUFFER, usage=GL_DYNAMIC_DRAW, 
           vbo=True, backed=False):
    '''Create a buffer of vertex data.
    '''
    if vbo and gl_info.have_version(1, 5):
        if backed:
            return BackedVertexBufferObject(size, target, usage)
        else:
            return VertexBufferObject(size, target, usage)
    else:
        return VertexArray(size)


class AbstractBuffer(object):
    #: Memory offset of buffer needed by glVertexPointer etc.
    ptr = 0
    #: Size of buffer, in bytes.
    size = 0

    def bind(self):
        raise NotImplementedError('abstract')

    def unbind(self):
        raise NotImplementedError('abstract')

    def set_data(self, data):
        raise NotImplementedError('abstract')

    def set_data_region(self, data, start, length):
        raise NotImplementedError('abstract')

    def map(self, invalidate=False):
        raise NotImplementedError('abstract')

    def unmap(self):
        raise NotImplementedError('abstract')

    def delete(self):
        raise NotImplementedError('abstract')

class VertexBufferObject(AbstractBuffer):
    def __init__(self, size, target, usage):
        self.size = size
        self.target = target
        self.usage = usage

        id = GLuint()
        glGenBuffers(1, id)
        self.id = id.value
        glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT)
        glBindBuffer(target, self.id)
        glBufferData(target, self.size, None, self.usage)
        glPopClientAttrib()

    def bind(self):
        glBindBuffer(self.target, self.id)

    def unbind(self):
        glBindBuffer(self.target, 0)

    def set_data(self, data):
        glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT)
        glBindBuffer(self.target, self.id)
        glBufferData(self.target, self.size, data, self.usage)
        glPopClientAttrib()

    def set_data_region(self, data, start, length):
        glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT)
        glBindBuffer(self.target, self.id)
        glBufferSubData(self.target, start, length, data)
        glPopClientAttrib()

    def map(self, invalidate=False):
        glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT)
        glBindBuffer(self.target, self.id)
        if invalidate:
            glBufferData(self.target, self.size, None, self.usage)
        glPopClientAttrib()
        return ctypes.cast(glMapBuffer(self.target, GL_WRITE_ONLY),
                           ctypes.POINTER(ctypes.c_byte * self.size)).contents

    def unmap(self):
        glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT)
        glUnmapBuffer(self.target)
        glPopClientAttrib()

    def delete(self):
        id = gl.GLuint(self.id)
        glDeleteBuffers(1, id)

    def resize(self, size):
        # Map, create a copy, then reinitialize.
        temp = (ctypes.c_byte * size)()

        glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT)
        glBindBuffer(self.target, self.id)
        data = glMapBuffer(self.target, GL_READ_ONLY)
        ctypes.memmove(temp, data, min(size, self.size))
        glUnmapBuffer(self.target)

        self.size = size
        glBufferData(self.target, self.size, temp, self.usage)
        glPopClientAttrib()

class BackedVertexBufferObject(VertexBufferObject):
    '''A VBO with system-memory backed store.
    
    Updates to the data via `set_data`, `set_data_region` and `map` will be
    held in local memory until `bind` is called.  The advantage is that fewer
    OpenGL calls are needed, increasing performance.  
    
    There may also be less performance penalty for resizing this buffer.

    Updates to data via `map` are committed immediately.
    '''
    def __init__(self, size, target, usage):
        super(BackedVertexBufferObject, self).__init__(size, target, usage)
        self.data = (ctypes.c_byte * size)()
        self.data_ptr = ctypes.cast(self.data, ctypes.c_void_p).value
        self._dirty = False

    def bind(self):
        # Commit pending data
        super(BackedVertexBufferObject, self).bind()
        if self._dirty:
            glBufferData(self.target, self.size, self.data, self.usage)
            self._dirty = False

    def set_data(self, data):
        super(VertexBufferObject, self).set_data(data)
        ctypes.memmove(self.data, data, self.size)
        self._dirty = True

    def set_data_region(self, data, start, length):
        ctypes.memmove(self.data_ptr + start, data, length)
        self._dirty = True

    def map(self, invalidate=False):
        self._dirty = True
        return self.data
        
    def unmap(self):
        pass

    def resize(self, size):
        data = (ctypes.c_byte * size)()
        ctypes.memmove(data, self.data, min(size, self.size))
        self.data = data
        self.data_ptr = ctypes.cast(self.data, ctypes.c_void_p).value
        
        self.size = size
        glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT)
        glBindBuffer(self.target, self.id)
        glBufferData(self.target, self.size, self.data, self.usage)
        glPopClientAttrib()


class VertexArray(AbstractBuffer):
    def __init__(self, size):
        self.size = size

        self.array = (ctypes.c_byte * size)()
{'fraction_non_alphanumeric': 0.10084905660377358, 'fraction_numerical': 0.0013207547169811322, 'mean_word_length': 2.6796251301631377, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '5369350', 'n_tokens_mistral': 3380, 'n_tokens_neox': 3339, 'n_words': 760}