def init_gl(self): '''initialize the opengl resources needed for presenting windows * a shader program * a vertex buffer * a texture for Label windows ''' self.program = GlProgram(shaders.vertex_flat, shaders.fragment_flat) self.buffer = gl.GLuint(0) gl.glGenBuffers(1, pointer(self.buffer)) self.texture = gl.GLuint(0) gl.glGenTextures(1, pointer(self.texture)) gl.glBindTexture(gl.GL_TEXTURE_2D, self.texture) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE) gl.glBindTexture(gl.GL_TEXTURE_2D, 0)
class WindowManager(): ''' The window manager is responsible for drawing the windows and for forwarding events to the windows. It uses a TextManager object to manage the texture resources used by the Label objects. The window manager creates an invisible root window which is the ancestor to all windows managed. ''' def __init__(self): '''initialize the WindowManager''' self.textmanager = TextManager() self.root = Window(None, 0, 0, 1, 1) self.root.manager = self self.init_gl() def init_gl(self): '''initialize the opengl resources needed for presenting windows * a shader program * a vertex buffer * a texture for Label windows ''' self.program = GlProgram(shaders.vertex_flat, shaders.fragment_flat) self.buffer = gl.GLuint(0) gl.glGenBuffers(1, pointer(self.buffer)) self.texture = gl.GLuint(0) gl.glGenTextures(1, pointer(self.texture)) gl.glBindTexture(gl.GL_TEXTURE_2D, self.texture) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE) gl.glBindTexture(gl.GL_TEXTURE_2D, 0) def draw(self): ''' Draw the windows. ''' self.program.use() data = list(self.root.get_data(0, 0)) data = (gl.GLfloat * len(data))(*data) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.buffer) gl.glBufferData(gl.GL_ARRAY_BUFFER, sizeof(data), data, gl.GL_DYNAMIC_DRAW) gl.glActiveTexture(gl.GL_TEXTURE0) gl.glBindTexture(gl.GL_TEXTURE_2D, self.texture) if self.textmanager.dirty: # only upload the texture to the GPU if it has actually changed gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, # level gl.GL_R8, self.textmanager.width, self.textmanager.height, 0, gl.GL_RED, gl.GL_UNSIGNED_BYTE, ctypes.create_string_buffer(self.textmanager.img.tobytes())) self.textmanager.dirty = False self.program.uniform1i(b"tex", 0) # set to 0 because the texture is bound to GL_TEXTURE0 self.program.vertex_attrib_pointer(self.buffer, b"position", 4) # self.program.vertex_attrib_pointer(self.buffer, b"texcoord", 2, stride=4 * sizeof(gl.GLfloat), offset=2 * sizeof(gl.GLfloat)) gl.glDrawArrays(gl.GL_QUADS, 0, len(data) // 4) def on_mouse_press(self, x, y, button, modifiers): '''forward the event to the root window''' return self.root.on_mouse_press(x, y, button, modifiers) def on_resize(self, x, y): '''update the window manager when the opengl viewport is resized''' self.program.uniform2f(b'window_size', x, -y)