def update_texture_rgb24(self, img_data, x, y, width, height, rowstride): drawable = self.glarea.get_gl_drawable() context = self.glarea.get_gl_context() if not drawable.gl_begin(context): raise Exception("** Cannot create OpenGL rendering context!") assert self.textures is not None glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[0]) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstride/3) if self.current_mode == GLClientWindow.MODE_YUV: raise Exception("** YUV -> RGB mode change unimplemented!") elif self.current_mode == GLClientWindow.MODE_UNINITIALIZED: log("Creating new RGB texture") w, h = self.get_size() # First time we draw must be full image assert w == width and h == height glEnable(GL_TEXTURE_RECTANGLE_ARB) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0) self.current_mode = GLClientWindow.MODE_RGB log("Updating RGB texture") glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, img_data) drawable.gl_end() self.render_image()
def _do_paint_rgb24(self, img_data, x, y, w, h, rowstride, options, callbacks): log("do_paint_rgb24(%s bytes, %s, %s, %s, %s, %s, %s, %s)", len(img_data), x, y, w, h, rowstride, options, callbacks) ww, wh = self.size if x+w>ww or y+h>wh: log("do_paint_rgb24: ignoring paint which would overflow the backing area") return drawable = self.gl_init() if not drawable: log("do_paint_rgb24: cannot paint yet..") return try: #cleanup if we were doing yuv previously: if self.pixel_format!=GLPixmapBacking.RGB24: self.remove_shader() self.pixel_format = GLPixmapBacking.RGB24 glEnable(GL_TEXTURE_RECTANGLE_ARB) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[0]) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstride/3) for texture in (GL_TEXTURE1, GL_TEXTURE2): glActiveTexture(texture) glDisable(GL_TEXTURE_RECTANGLE_ARB) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, w, h, GL_RGB, GL_UNSIGNED_BYTE, img_data) glBegin(GL_QUADS) for rx,ry in ((x, y), (x, y+h), (x+w, y+h), (x+w, y)): glTexCoord2i(rx, ry) glVertex2i(rx, ry) glEnd() finally: self.gl_end(drawable)
def update_texture_rgb24(self, img_data, x, y, width, height, rowstride): drawable = self.glarea.get_gl_drawable() context = self.glarea.get_gl_context() if not drawable.gl_begin(context): raise Exception("** Cannot create OpenGL rendering context!") assert self.textures is not None glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[0]) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstride / 3) if self.current_mode == GLClientWindow.MODE_YUV: raise Exception("** YUV -> RGB mode change unimplemented!") elif self.current_mode == GLClientWindow.MODE_UNINITIALIZED: log("Creating new RGB texture") w, h = self.get_size() # First time we draw must be full image assert w == width and h == height glEnable(GL_TEXTURE_RECTANGLE_ARB) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0) self.current_mode = GLClientWindow.MODE_RGB log("Updating RGB texture") glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, img_data) drawable.gl_end() self.render_image()
def update_planar_textures(self, x, y, width, height, img, pixel_format, scaling=False): assert self.textures is not None, "no OpenGL textures!" log("%s.update_planar_textures%s", self, (x, y, width, height, img, pixel_format)) divs = get_subsampling_divs(pixel_format) if self.pixel_format is None or self.pixel_format!=pixel_format or self.texture_size!=(width, height): self.pixel_format = pixel_format self.texture_size = (width, height) self.gl_marker("Creating new planar textures, pixel format %s", pixel_format) # Create textures of the same size as the window's empty_buf = b"\0"*(width*height) pixel_data = self.pixels_for_upload(empty_buf)[1] for texture, index in ((GL_TEXTURE0, TEX_Y), (GL_TEXTURE1, TEX_U), (GL_TEXTURE2, TEX_V)): (div_w, div_h) = divs[index] glActiveTexture(texture) target = GL_TEXTURE_RECTANGLE_ARB glBindTexture(target, self.textures[index]) mag_filter = GL_NEAREST if scaling or (div_w > 1 or div_h > 1): mag_filter = GL_LINEAR glTexParameteri(target, GL_TEXTURE_MAG_FILTER, mag_filter) glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST) set_texture_level() glTexImage2D(target, 0, GL_LUMINANCE, width//div_w, height//div_h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, pixel_data) #glBindTexture(target, 0) #redundant: we rebind below: self.gl_marker("updating planar textures: %sx%s %s", width, height, pixel_format) rowstrides = img.get_rowstride() img_data = img.get_pixels() assert len(rowstrides)==3 and len(img_data)==3 for texture, index, tex_name in ( (GL_TEXTURE0, TEX_Y, "Y"), (GL_TEXTURE1, TEX_U, "U"), (GL_TEXTURE2, TEX_V, "V"), ): div_w, div_h = divs[index] w = width//div_w h = height//div_h if w==0 or h==0: log.error("Error: zero dimension %ix%i for %s planar texture %s", w, h, pixel_format, tex_name) log.error(" screen update %s dropped", (x, y, width, height)) continue glActiveTexture(texture) target = GL_TEXTURE_RECTANGLE_ARB glBindTexture(target, self.textures[index]) self.set_alignment(w, rowstrides[index], tex_name) upload, pixel_data = self.pixels_for_upload(img_data[index]) log("texture %s: div=%s, rowstride=%s, %sx%s, data=%s bytes, upload=%s", index, divs[index], rowstrides[index], w, h, len(pixel_data), upload) glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0) try: glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, 0) except: pass glTexSubImage2D(target, 0, 0, 0, w, h, GL_LUMINANCE, GL_UNSIGNED_BYTE, pixel_data) glBindTexture(target, 0)
def update_planar_textures(self, x, y, width, height, img, pixel_format, scaling=False): assert self.textures is not None, "no OpenGL textures!" log("%s.update_planar_textures%s", self, (x, y, width, height, img, pixel_format)) divs = get_subsampling_divs(pixel_format) if self.pixel_format is None or self.pixel_format != pixel_format or self.texture_size != ( width, height): self.pixel_format = pixel_format self.texture_size = (width, height) self.gl_marker("Creating new planar textures, pixel format %s" % pixel_format) # Create textures of the same size as the window's glEnable(GL_TEXTURE_RECTANGLE_ARB) for texture, index in ((GL_TEXTURE0, 0), (GL_TEXTURE1, 1), (GL_TEXTURE2, 2)): (div_w, div_h) = divs[index] glActiveTexture(texture) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[index]) glEnable(GL_TEXTURE_RECTANGLE_ARB) mag_filter = GL_NEAREST if scaling or (div_w > 1 or div_h > 1): mag_filter = GL_LINEAR glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, mag_filter) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, width / div_w, height / div_h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, None) self.gl_marker("updating planar textures: %sx%s %s" % (width, height, pixel_format)) rowstrides = img.get_rowstride() img_data = img.get_pixels() assert len(rowstrides) == 3 and len(img_data) == 3 for texture, index in ((GL_TEXTURE0, 0), (GL_TEXTURE1, 1), (GL_TEXTURE2, 2)): (div_w, div_h) = divs[index] glActiveTexture(texture) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[index]) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstrides[index]) pixel_data = img_data[index] log("texture %s: div=%s, rowstride=%s, %sx%s, data=%s bytes", index, divs[index], rowstrides[index], width / div_w, height / div_h, len(pixel_data)) glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width / div_w, height / div_h, GL_LUMINANCE, GL_UNSIGNED_BYTE, pixel_data)
def update_texture_yuv(self, img_data, x, y, width, height, rowstrides, pixel_format): assert x==0 and y==0 assert self.textures is not None, "no OpenGL textures!" if self.pixel_format is None or self.pixel_format!=pixel_format or self.texture_size!=(width, height): self.pixel_format = pixel_format self.texture_size = (width, height) divs = get_subsampling_divs(pixel_format) debug("GL creating new YUV textures for pixel format %s using divs=%s", pixel_format, divs) self.gl_marker("Creating new YUV textures") # Create textures of the same size as the window's glEnable(GL_TEXTURE_RECTANGLE_ARB) for texture, index in ((GL_TEXTURE0, 0), (GL_TEXTURE1, 1), (GL_TEXTURE2, 2)): (div_w, div_h) = divs[index] glActiveTexture(texture) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[index]) glEnable(GL_TEXTURE_RECTANGLE_ARB) mag_filter = GL_NEAREST if div_w > 1 or div_h > 1: mag_filter = GL_LINEAR glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, mag_filter) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, width/div_w, height/div_h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0) debug("Assigning fragment program") glEnable(GL_FRAGMENT_PROGRAM_ARB) if not self.yuv_shader: self.yuv_shader = [ 1 ] glGenProgramsARB(1, self.yuv_shader) glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, self.yuv_shader[0]) prog = GL_COLORSPACE_CONVERSIONS glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, len(prog), prog) err = glGetString(GL_PROGRAM_ERROR_STRING_ARB) if err: #FIXME: maybe we should do something else here? log.error(err) self.gl_marker("Updating YUV textures") divs = get_subsampling_divs(pixel_format) U_width = 0 U_height = 0 for texture, index in ((GL_TEXTURE0, 0), (GL_TEXTURE1, 1), (GL_TEXTURE2, 2)): (div_w, div_h) = divs[index] glActiveTexture(texture) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[index]) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstrides[index]) glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, width/div_w, height/div_h, GL_LUMINANCE, GL_UNSIGNED_BYTE, img_data[index]) if index == 1: U_width = width/div_w U_height = height/div_h elif index == 2: if width/div_w != U_width: log.error("Width of V plane is %d, differs from width of corresponding U plane (%d), pixel_format is %d", width/div_w, U_width, pixel_format) if height/div_h != U_height: log.error("Height of V plane is %d, differs from height of corresponding U plane (%d)", height/div_h, U_height)
def refresh(self): img = self.textureData mi, ma = self.histogramScale pic_ny, pic_nx = img.shape if img.dtype.type in (numpy.float64, numpy.int32, numpy.uint32): data = img.astype(numpy.float32) imgString = data.tostring() imgType = numpy.float32 else: imgString = img.tostring() imgType = img.dtype.type # maxUShort: value that represents "maximum color" - i.e. white if img.dtype.type == numpy.uint16: maxUShort = (1 << 16) - 1 elif img.dtype.type == numpy.int16: maxUShort = (1 << 15) - 1 elif img.dtype.type == numpy.uint8: maxUShort = (1 << 8) - 1 else: maxUShort = 1 mmrange = float(ma) - float(mi) fBias = -float(mi) / mmrange f = maxUShort / mmrange glBindTexture(GL_TEXTURE_2D, self.texture) glPixelTransferf(GL_RED_SCALE, f) glPixelTransferf(GL_GREEN_SCALE, f) glPixelTransferf(GL_BLUE_SCALE, f) glPixelTransferf(GL_RED_BIAS, fBias) glPixelTransferf(GL_GREEN_BIAS, fBias) glPixelTransferf(GL_BLUE_BIAS, fBias) glPixelTransferi(GL_MAP_COLOR, False) if img.dtype.type in (numpy.float64, numpy.int32, numpy.uint32, numpy.complex64, numpy.complex128): itSize = 4 glPixelStorei(GL_UNPACK_SWAP_BYTES, False) # create native float32 copy - see below else: itSize = img.itemsize glPixelStorei(GL_UNPACK_SWAP_BYTES, not img.dtype.isnative) glPixelStorei(GL_UNPACK_ALIGNMENT, itSize) if imgType not in dtypeToGlTypeMap: raise ValueError("Unsupported data mode %s" % str(imgType)) glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, pic_nx, pic_ny, GL_LUMINANCE, dtypeToGlTypeMap[imgType], imgString)
def update_texture_yuv(self, img_data, x, y, width, height, rowstrides, pixel_format): window_width, window_height = self.size assert self.textures is not None, "no OpenGL textures!" if self.pixel_format is None or self.pixel_format!=pixel_format: self.pixel_format = pixel_format divs = self.get_subsampling_divs(pixel_format) log("GL creating new YUV textures for pixel format %s using divs=%s", pixel_format, divs) # Create textures of the same size as the window's glEnable(GL_TEXTURE_RECTANGLE_ARB) for texture, index in ((GL_TEXTURE0, 0), (GL_TEXTURE1, 1), (GL_TEXTURE2, 2)): div = divs[index] glActiveTexture(texture) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[index]) glEnable(GL_TEXTURE_RECTANGLE_ARB) mag_filter = GL_NEAREST if div>1: mag_filter = GL_LINEAR glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, mag_filter) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, window_width/div, window_height/div, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0) log("Assigning fragment program") glEnable(GL_FRAGMENT_PROGRAM_ARB) if not self.yuv_shader: self.yuv_shader = [ 1 ] glGenProgramsARB(1, self.yuv_shader) glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, self.yuv_shader[0]) prog = GL_COLORSPACE_CONVERSIONS glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, len(prog), prog) err = glGetString(GL_PROGRAM_ERROR_STRING_ARB) if err: #FIXME: maybe we should do something else here? log.error(err) glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, self.yuv_shader[0]) # Clamp width and height to the actual texture size if x + width > window_width: width = window_width - x if y + height > window_height: height = window_height - y divs = self.get_subsampling_divs(pixel_format) for texture, index in ((GL_TEXTURE0, 0), (GL_TEXTURE1, 1), (GL_TEXTURE2, 2)): div = divs[index] glActiveTexture(texture) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[index]) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstrides[index]) glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, width/div, height/div, GL_LUMINANCE, GL_UNSIGNED_BYTE, img_data[index]) glFlush()
def update_planar_textures(self, x, y, width, height, img, pixel_format, scaling=False): assert x==0 and y==0 assert self.textures is not None, "no OpenGL textures!" debug("%s.update_planar_textures%s", self, (x, y, width, height, img, pixel_format)) divs = get_subsampling_divs(pixel_format) if self.pixel_format is None or self.pixel_format!=pixel_format or self.texture_size!=(width, height): self.pixel_format = pixel_format self.texture_size = (width, height) self.gl_marker("Creating new planar textures, pixel format %s" % pixel_format) # Create textures of the same size as the window's glEnable(GL_TEXTURE_RECTANGLE_ARB) for texture, index in ((GL_TEXTURE0, 0), (GL_TEXTURE1, 1), (GL_TEXTURE2, 2)): (div_w, div_h) = divs[index] glActiveTexture(texture) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[index]) glEnable(GL_TEXTURE_RECTANGLE_ARB) mag_filter = GL_NEAREST if scaling or (div_w > 1 or div_h > 1): mag_filter = GL_LINEAR glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, mag_filter) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, width/div_w, height/div_h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, None) self.gl_marker("updating planar textures: %sx%s %s" % (width, height, pixel_format)) U_width = 0 U_height = 0 rowstrides = img.get_rowstride() img_data = img.get_pixels() assert len(rowstrides)==3 assert len(img_data)==3 for texture, index in ((GL_TEXTURE0, 0), (GL_TEXTURE1, 1), (GL_TEXTURE2, 2)): (div_w, div_h) = divs[index] glActiveTexture(texture) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[index]) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstrides[index]) pixel_data = img_data[index][:] debug("texture %s: div=%s, rowstride=%s, %sx%s, data=%s bytes", index, divs[index], rowstrides[index], width/div_w, height/div_h, len(pixel_data)) glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, width/div_w, height/div_h, GL_LUMINANCE, GL_UNSIGNED_BYTE, pixel_data) if index == 1: U_width = width/div_w U_height = height/div_h elif index == 2: if width/div_w != U_width: log.error("Width of V plane is %d, differs from width of corresponding U plane (%d), pixel_format is %d", width/div_w, U_width, pixel_format) if height/div_h != U_height: log.error("Height of V plane is %d, differs from height of corresponding U plane (%d), pixel_format is %d", height/div_h, U_height, pixel_format)
def from_matrix(cls, matrix): """Creates a texture from given matrix file. :param matrix: The matrix. :type matrix: list :returns: The texture instance. :rtype: :class:`renderer.Texture` """ w, h = len(matrix[0]), len(matrix) grid = bytes(chain.from_iterable(reversed(matrix))) tex = glGenTextures(1) glActiveTexture(GL_TEXTURE0) glBindTexture(GL_TEXTURE_2D, tex) # This code is necessary to handle non-power-of-two textures with small # sizes. # TODO: refactor this param_ids = [ GL_UNPACK_ALIGNMENT, GL_UNPACK_ROW_LENGTH, GL_UNPACK_SKIP_ROWS, GL_UNPACK_SKIP_PIXELS, ] old_params = { p: glGetInteger(p) for p in param_ids } glPixelStorei(GL_UNPACK_ALIGNMENT, 1) glPixelStorei(GL_UNPACK_ROW_LENGTH, 0) glPixelStorei(GL_UNPACK_SKIP_ROWS, 0) glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0) glTexStorage2D(GL_TEXTURE_2D, 1, GL_R8, w, h) glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RED, GL_UNSIGNED_BYTE, grid) for p, v in old_params.items(): glPixelStorei(p, v) glBindTexture(GL_TEXTURE_2D, 0) return Texture(tex, w, h, GL_TEXTURE_2D)
def render_to_texture(self, text): """Renders the given string to a texture object. :param text: Text to render. :type text: str :returns: The resulting texture object. :rtype: :class:`renderer.Texture` """ # render the text to a SDL_Surface structure surf_ptr = ttf.TTF_RenderText_Solid( self.font, text.encode('utf8'), sdl.SDL_Color()) if not surf_ptr: raise SDLError('failed to render text to surface: {}'.format( ttf.TTF_GetError())) # retrieve a pointer to pixel data surf = surf_ptr.contents pixels = ctypes.cast(surf.pixels, ctypes.POINTER(ctypes.c_char)) # create and fill an OpenGL rectangle texture (that is, a texture which # can have arbitrary non-power-of-two size and is accessed using # UV coordinates which are linearly mapped to the texture size) tex = glGenTextures(1) glActiveTexture(GL_TEXTURE0) glBindTexture(GL_TEXTURE_2D, tex) glTexStorage2D(GL_TEXTURE_2D, 1, GL_R8, surf.w, surf.h) glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, surf.w, surf.h, GL_RED, GL_UNSIGNED_BYTE, pixels) glBindTexture(GL_TEXTURE_2D, 0) sdl.SDL_FreeSurface(surf_ptr) return Texture(tex, surf.w, surf.h, GL_TEXTURE_2D)
def blit_buffer(self, buffer, size=None, mode='RGB', format=None, pos=(0, 0), buffertype=GL_UNSIGNED_BYTE): '''Blit a buffer into a texture. :Parameters: `buffer` : str Image data `size` : tuple, default to texture size Size of the image (width, height) `mode` : str, default to 'RGB' Image mode, can be one of RGB, RGBA, BGR, BGRA `format` : glconst, default to None if format is passed, it will be used instead of mode `pos` : tuple, default to (0, 0) Position to blit in the texture `buffertype` : glglconst, default to GL_UNSIGNED_BYTE Type of the data buffer ''' if size is None: size = self.size if format is None: format = self.mode_to_gl_format(mode) target = self.target glBindTexture(target, self.id) glEnable(target) # activate 1 alignement, of window failed on updating weird size glPixelStorei(GL_UNPACK_ALIGNMENT, 1) # need conversion ? pdata, format = self._convert_buffer(buffer, format) # transfer the new part of texture glTexSubImage2D(target, 0, pos[0], pos[1], size[0], size[1], format, buffertype, pdata) glFlush() glDisable(target)
def from_image(cls, image): """Creates a texture from given image file. :param image: Image. :type image: :class:`PIL.Image` :returns: The texture instance. :rtype: :class:`renderer.Texture` """ w, h = image.size tex = glGenTextures(1) glActiveTexture(GL_TEXTURE0) glBindTexture(GL_TEXTURE_2D, tex) glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, w, h) glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, image.tobytes()) glBindTexture(GL_TEXTURE_2D, 0) return Texture(tex, w, h)
def update_planar_textures(self, x, y, width, height, img, pixel_format, scaling=False): assert self.textures is not None, "no OpenGL textures!" log("%s.update_planar_textures%s", self, (x, y, width, height, img, pixel_format)) divs = get_subsampling_divs(pixel_format) if self.pixel_format is None or self.pixel_format!=pixel_format or self.texture_size!=(width, height): self.pixel_format = pixel_format self.texture_size = (width, height) self.gl_marker("Creating new planar textures, pixel format %s", pixel_format) # Create textures of the same size as the window's glEnable(GL_TEXTURE_RECTANGLE_ARB) for texture, index in ((GL_TEXTURE0, 0), (GL_TEXTURE1, 1), (GL_TEXTURE2, 2)): (div_w, div_h) = divs[index] glActiveTexture(texture) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[index]) glEnable(GL_TEXTURE_RECTANGLE_ARB) mag_filter = GL_NEAREST if scaling or (div_w > 1 or div_h > 1): mag_filter = GL_LINEAR glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, mag_filter) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) set_texture_level() glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, width//div_w, height//div_h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, None) self.gl_marker("updating planar textures: %sx%s %s", width, height, pixel_format) rowstrides = img.get_rowstride() img_data = img.get_pixels() assert len(rowstrides)==3 and len(img_data)==3 for texture, index in ((GL_TEXTURE0, 0), (GL_TEXTURE1, 1), (GL_TEXTURE2, 2)): (div_w, div_h) = divs[index] glActiveTexture(texture) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[index]) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstrides[index]) upload, pixel_data = self.pixels_for_upload(img_data[index]) log("texture %s: div=%s, rowstride=%s, %sx%s, data=%s bytes, upload=%s", index, divs[index], rowstrides[index], width//div_w, height//div_h, len(pixel_data), upload) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_BASE_LEVEL, 0) try: glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAX_LEVEL, 0) except: pass glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width//div_w, height//div_h, GL_LUMINANCE, GL_UNSIGNED_BYTE, pixel_data)
def _do_paint_rgb24(self, img_data, x, y, w, h, rowstride, options, callbacks): log("do_paint_rgb24(%s bytes, %s, %s, %s, %s, %s, %s, %s)", len(img_data), x, y, w, h, rowstride, options, callbacks) ww, wh = self.size if x + w > ww or y + h > wh: log("do_paint_rgb24: ignoring paint which would overflow the backing area" ) return drawable = self.gl_init() if not drawable: log("do_paint_rgb24: cannot paint yet..") return try: #cleanup if we were doing yuv previously: if self.pixel_format != GLPixmapBacking.RGB24: self.remove_shader() self.pixel_format = GLPixmapBacking.RGB24 glEnable(GL_TEXTURE_RECTANGLE_ARB) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[0]) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstride / 3) for texture in (GL_TEXTURE1, GL_TEXTURE2): glActiveTexture(texture) glDisable(GL_TEXTURE_RECTANGLE_ARB) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, w, h, GL_RGB, GL_UNSIGNED_BYTE, img_data) glBegin(GL_QUADS) for rx, ry in ((x, y), (x, y + h), (x + w, y + h), (x + w, y)): glTexCoord2i(rx, ry) glVertex2i(rx, ry) glEnd() finally: self.gl_end(drawable)
def update(self, pil_image: Image.Image): """Update the texture to contain the provided image. :param pil_image: The image to write into the texture. """ # Ensure the image is in RGBA format and convert to the raw RGBA bytes. image_width, image_height = pil_image.size image = pil_image.convert("RGBA").tobytes("raw", "RGBA") # Bind the texture so that it can be modified. self.bind() if (self._width == image_width) and (self._height == image_height): # Same size - just need to update the texels. glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image_width, image_height, GL_RGBA, GL_UNSIGNED_BYTE, image) else: # Different size than the last frame (e.g. the Window is resizing) # Create a new texture of the correct size. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image_width, image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image) self._width = image_width self._height = image_height
def setupTransforms(self, transforms): # note: this is only called from test_drawing.py (as of before 090302) """ Fill a block of transforms. Depending on the setting of TEXTURE_XFORMS and UNIFORM_XFORMS, the transforms are either in texture memory, or in a uniform array of mat4s ("constant memory"), or unsupported (error if we need any here). @param transforms: A list of transform matrices, where each transform is a flattened list (or Numpy array) of 16 numbers. """ self.n_transforms = nTransforms = len(transforms) if not self.supports_transforms(): assert not nTransforms, "%r doesn't support transforms" % self return self.setActive(True) # Must activate before setting uniforms. assert self._has_uniform("n_transforms") # redundant with following glUniform1iARB(self._uniform("n_transforms"), self.n_transforms) # The shader bypasses transform logic if n_transforms is 0. # (Then location coordinates are in global modeling coordinates.) if nTransforms > 0: if UNIFORM_XFORMS: # Load into constant memory. The GL_EXT_bindable_uniform # extension supports sharing this array of mat4s through a VBO. # XXX Need to bank-switch this data if more than N_CONST_XFORMS. C_transforms = numpy.array(transforms, dtype = numpy.float32) glUniformMatrix4fvARB(self._uniform("transforms"), # Don't over-run the array size. min(len(transforms), N_CONST_XFORMS), GL_TRUE, # Transpose. C_transforms) elif TEXTURE_XFORMS: # Generate a texture ID and bind the texture unit to it. self.transform_memory = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, self.transform_memory) ## These seem to have no effect with a vertex shader. ## glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) ## glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) # XXX Needed? glEnable(GL_TEXTURE_2D) # Load the transform data into the texture. # # Problem: SIGSEGV kills Python in gleTextureImagePut under # glTexImage2D with more than 250 transforms (16,000 bytes.) # Maybe there's a 16-bit signed size calculation underthere, that's # overflowing the sign bit... Work around by sending transforms to # the texture unit in batches with glTexSubImage2D.) glTexImage2D(GL_TEXTURE_2D, 0, # Level zero - base image, no mipmap. GL_RGBA32F_ARB, # Internal format is floating point. # Column major storage: width = N, height = 4 * RGBA. nTransforms, 4 * 4, 0, # No border. # Data format and type, null pointer to allocate space. GL_RGBA, GL_FLOAT, None) # XXX Split this off into a setTransforms method. batchSize = 250 nBatches = (nTransforms + batchSize-1) / batchSize for i in range(nBatches): xStart = batchSize * i xEnd = min(nTransforms, xStart + batchSize) xSize = xEnd - xStart glTexSubImage2D(GL_TEXTURE_2D, 0, # Subimage x and y offsets and sizes. xStart, 0, xSize, 4 * 4, # List of matrices is flattened into a sequence. GL_RGBA, GL_FLOAT, transforms[xStart:xEnd]) continue # Read back to check proper loading. if CHECK_TEXTURE_XFORM_LOADING: mats = glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT) nMats = len(mats) print "setupTransforms\n[[", for i in range(nMats): nElts = len(mats[i]) perLine = 8 nLines = (nElts + perLine-1) / perLine for line in range(nLines): jStart = perLine * line jEnd = min(nElts, jStart + perLine) for j in range(jStart, jEnd): print "%.2f" % mats[i][j], continue if line < nLines-1: print "\n ", pass if i < nMats-1: print "]\n [", pass continue print "]]" pass else: # should never happen if SUPPORTS_XFORMS is defined correctly assert 0, "can't setupTransforms unless UNIFORM_XFORMS or TEXTURE_XFORMS is set" pass self.setActive(False) # Deactivate again. return
def update_texture_yuv(self, img_data, x, y, width, height, rowstrides, pixel_format): window_width, window_height = self.size assert self.textures is not None, "no OpenGL textures!" if self.pixel_format is None or self.pixel_format != pixel_format: self.pixel_format = pixel_format divs = self.get_subsampling_divs(pixel_format) log( "GL creating new YUV textures for pixel format %s using divs=%s", pixel_format, divs) # Create textures of the same size as the window's glEnable(GL_TEXTURE_RECTANGLE_ARB) for texture, index in ((GL_TEXTURE0, 0), (GL_TEXTURE1, 1), (GL_TEXTURE2, 2)): div = divs[index] glActiveTexture(texture) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[index]) glEnable(GL_TEXTURE_RECTANGLE_ARB) mag_filter = GL_NEAREST if div > 1: mag_filter = GL_LINEAR glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, mag_filter) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, window_width / div, window_height / div, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0) log("Assigning fragment program") glEnable(GL_FRAGMENT_PROGRAM_ARB) if not self.yuv_shader: self.yuv_shader = [1] glGenProgramsARB(1, self.yuv_shader) glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, self.yuv_shader[0]) prog = GL_COLORSPACE_CONVERSIONS glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, len(prog), prog) err = glGetString(GL_PROGRAM_ERROR_STRING_ARB) if err: #FIXME: maybe we should do something else here? log.error(err) glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, self.yuv_shader[0]) # Clamp width and height to the actual texture size if x + width > window_width: width = window_width - x if y + height > window_height: height = window_height - y divs = self.get_subsampling_divs(pixel_format) for texture, index in ((GL_TEXTURE0, 0), (GL_TEXTURE1, 1), (GL_TEXTURE2, 2)): div = divs[index] glActiveTexture(texture) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[index]) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstrides[index]) glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, width / div, height / div, GL_LUMINANCE, GL_UNSIGNED_BYTE, img_data[index]) glFlush()
def update_texture_yuv420(self, img_data, x, y, width, height, rowstrides): drawable = self.glarea.get_gl_drawable() context = self.glarea.get_gl_context() window_width, window_height = self.get_size() if not drawable.gl_begin(context): raise Exception("** Cannot create OpenGL rendering context!") assert self.textures is not None if self.current_mode == GLClientWindow.MODE_RGB: raise Exception("** RGB -> YUV mode change unimplemented!") elif self.current_mode == GLClientWindow.MODE_UNINITIALIZED: log("Creating new YUV textures") # Create textures of the same size as the window's glEnable(GL_TEXTURE_RECTANGLE_ARB) glActiveTexture(GL_TEXTURE0) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[0]) glEnable(GL_TEXTURE_RECTANGLE_ARB) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, window_width, window_height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0) glActiveTexture(GL_TEXTURE1) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[1]) glEnable(GL_TEXTURE_RECTANGLE_ARB) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, window_width / 2, window_height / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0) glActiveTexture(GL_TEXTURE2) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[2]) glEnable(GL_TEXTURE_RECTANGLE_ARB) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, window_width / 2, window_height / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0) log("Assigning fragment program") glEnable(GL_FRAGMENT_PROGRAM_ARB) if not self.yuv420_shader: self.yuv420_shader = [1] glGenProgramsARB(1, self.yuv420_shader) glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, self.yuv420_shader[0]) prog = GL_COLORSPACE_CONVERSIONS glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, len(prog), prog) log.error(glGetString(GL_PROGRAM_ERROR_STRING_ARB)) glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, self.yuv420_shader[0]) self.current_mode = GLClientWindow.MODE_YUV # Clamp width and height to the actual texture size if x + width > window_width: width = window_width - x if y + height > window_height: height = window_height - y glActiveTexture(GL_TEXTURE0) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[0]) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstrides[0]) glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, img_data[0]) glActiveTexture(GL_TEXTURE1) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[1]) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstrides[1]) glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, width / 2, height / 2, GL_LUMINANCE, GL_UNSIGNED_BYTE, img_data[1]) glActiveTexture(GL_TEXTURE2) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[2]) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstrides[2]) glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, width / 2, height / 2, GL_LUMINANCE, GL_UNSIGNED_BYTE, img_data[2]) drawable.gl_end() self.render_image()
def update_texture_yuv420(self, img_data, x, y, width, height, rowstrides): drawable = self.glarea.get_gl_drawable() context = self.glarea.get_gl_context() window_width, window_height = self.get_size() if not drawable.gl_begin(context): raise Exception("** Cannot create OpenGL rendering context!") assert self.textures is not None if self.current_mode == GLClientWindow.MODE_RGB: raise Exception("** RGB -> YUV mode change unimplemented!") elif self.current_mode == GLClientWindow.MODE_UNINITIALIZED: log("Creating new YUV textures") # Create textures of the same size as the window's glEnable(GL_TEXTURE_RECTANGLE_ARB) glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[0]) glEnable(GL_TEXTURE_RECTANGLE_ARB) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, window_width, window_height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[1]) glEnable(GL_TEXTURE_RECTANGLE_ARB) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, window_width/2, window_height/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[2]) glEnable(GL_TEXTURE_RECTANGLE_ARB) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, window_width/2, window_height/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0); log("Assigning fragment program") glEnable(GL_FRAGMENT_PROGRAM_ARB) if not self.yuv420_shader: self.yuv420_shader = [ 1 ] glGenProgramsARB(1, self.yuv420_shader) glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, self.yuv420_shader[0]) prog = GL_COLORSPACE_CONVERSIONS glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, len(prog), prog) log.error(glGetString(GL_PROGRAM_ERROR_STRING_ARB)) glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, self.yuv420_shader[0]) self.current_mode = GLClientWindow.MODE_YUV # Clamp width and height to the actual texture size if x + width > window_width: width = window_width - x if y + height > window_height: height = window_height - y glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[0]) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstrides[0]) glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, img_data[0]) glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[1]) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstrides[1]) glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, width/2, height/2, GL_LUMINANCE, GL_UNSIGNED_BYTE, img_data[1]) glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[2]) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstrides[2]) glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, width/2, height/2, GL_LUMINANCE, GL_UNSIGNED_BYTE, img_data[2]) drawable.gl_end() self.render_image()
def update_texture_yuv(self, img_data, x, y, width, height, rowstrides, pixel_format): assert x == 0 and y == 0 assert self.textures is not None, "no OpenGL textures!" if self.pixel_format is None or self.pixel_format != pixel_format or self.texture_size != ( width, height): self.pixel_format = pixel_format self.texture_size = (width, height) divs = get_subsampling_divs(pixel_format) debug( "GL creating new YUV textures for pixel format %s using divs=%s", pixel_format, divs) self.gl_marker("Creating new YUV textures") # Create textures of the same size as the window's glEnable(GL_TEXTURE_RECTANGLE_ARB) for texture, index in ((GL_TEXTURE0, 0), (GL_TEXTURE1, 1), (GL_TEXTURE2, 2)): (div_w, div_h) = divs[index] glActiveTexture(texture) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[index]) glEnable(GL_TEXTURE_RECTANGLE_ARB) mag_filter = GL_NEAREST if div_w > 1 or div_h > 1: mag_filter = GL_LINEAR glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, mag_filter) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, width / div_w, height / div_h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0) debug("Assigning fragment program") glEnable(GL_FRAGMENT_PROGRAM_ARB) if not self.yuv_shader: self.yuv_shader = [1] glGenProgramsARB(1, self.yuv_shader) glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, self.yuv_shader[0]) prog = GL_COLORSPACE_CONVERSIONS glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, len(prog), prog) err = glGetString(GL_PROGRAM_ERROR_STRING_ARB) if err: #FIXME: maybe we should do something else here? log.error(err) self.gl_marker("Updating YUV textures") divs = get_subsampling_divs(pixel_format) U_width = 0 U_height = 0 for texture, index in ((GL_TEXTURE0, 0), (GL_TEXTURE1, 1), (GL_TEXTURE2, 2)): (div_w, div_h) = divs[index] glActiveTexture(texture) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[index]) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstrides[index]) glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, width / div_w, height / div_h, GL_LUMINANCE, GL_UNSIGNED_BYTE, img_data[index]) if index == 1: U_width = width / div_w U_height = height / div_h elif index == 2: if width / div_w != U_width: log.error( "Width of V plane is %d, differs from width of corresponding U plane (%d), pixel_format is %d", width / div_w, U_width, pixel_format) if height / div_h != U_height: log.error( "Height of V plane is %d, differs from height of corresponding U plane (%d)", height / div_h, U_height)
def setup(self): ''' Construct the texture atlas for the font ''' face = Face(self.filename) face.set_pixel_sizes(0, self.size) rowh, roww = 0,0 # Determine image size for i in xrange(32,128): face.load_char( chr(i), FT_LOAD_RENDER) bitmap = face.glyph.bitmap if roww + bitmap.width + 1 >= 1024: # max texture width self.w = max(self.w, roww) self.h += rowh roww = 0 rowh = 0 roww += bitmap.width + 1 rowh = max(rowh, bitmap.rows) self.w = max(self.w, roww) self.h += rowh ## Create texture to hold ASCII glyphs # Ensure no texture is currently selected glActiveTexture(GL_TEXTURE0) self.texid = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, self.texid) glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, self.w, self.h, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0) # We require 1 byte alignment when uploading texture data glPixelStorei(GL_UNPACK_ALIGNMENT, 1) # Clamping to edges is important to prevent artifacts when scaling glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) # Linear filtering looks better for text glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) # Add glyphs to texture ox = 0 oy = 0 rowh = 0 # class to hold data class CharInfo: pass for i in xrange(32,128): face.load_char( chr(i), FT_LOAD_RENDER) g = face.glyph bitmap = g.bitmap if ox + bitmap.width + 1 >= 1024: # max texture width oy += rowh rowh = 0 ox = 0 glTexSubImage2D(GL_TEXTURE_2D, 0, ox, oy, bitmap.width, bitmap.rows, GL_ALPHA, GL_UNSIGNED_BYTE, bitmap.buffer) ci = CharInfo() ci.ax = float(g.advance.x >> 6) ci.ay = float(g.advance.y >> 6) ci.bw = float(bitmap.width) ci.bh = float(bitmap.rows) ci.bl = float(g.bitmap_left) ci.bt = float(g.bitmap_top) ci.tx = float(ox) / float(self.w) ci.ty = float(oy) / float(self.h) self.c[chr(i)] = ci rowh = max(rowh, bitmap.rows) ox += bitmap.width + 1