Source code for cairotft.linuxfb

# Copyright (c) 2012 Kurichan
#
# This program is free software. It comes without any warranty, to
# the extent permitted by applicable law. You can redistribute it
# and/or modify it under the terms of the Do What The Fuck You Want
# To Public License, Version 2, as published by Sam Hocevar. See
# http://sam.zoy.org/wtfpl/COPYING for more details.
"""Small wrapping of linux/fb.h.

update for cairotft: this module has been modified to support
        double buffering and is not api-compatible anymore with the original
        module from Kurichan.

        It has also been modified for python 3.4 compat'
"""
import os
import mmap
import ctypes
from fcntl import ioctl

#
# Working without ctypes example
#
# >>> buf = array.array('B', (0x00,)*(16+8+4))
# >>> fcntl.ioctl(fid, 0x4602, buf)
# 0
# >>> struct.unpack('I', buf[-4:])
# (2457600,)
#

FBIOGET_VSCREENINFO = 0x4600
FBIOGET_FSCREENINFO = 0x4602


[docs]class FbFid(int): """The framebuffer file descriptor. The name attribute gives the opened framebuffer file. """ # __slots__ = ('name',) pass
[docs]class FixScreenInfo(ctypes.Structure): """The fb_fix_screeninfo from fb.h.""" _fields_ = [ ('id_name', ctypes.c_char * 16), ('smem_start', ctypes.c_ulong), ('smem_len', ctypes.c_uint32), ('type', ctypes.c_uint32), ('type_aux', ctypes.c_uint32), ('visual', ctypes.c_uint32), ('xpanstep', ctypes.c_uint16), ('ypanstep', ctypes.c_uint16), ('ywrapstep', ctypes.c_uint16), ('line_length', ctypes.c_uint32), ('mmio_start', ctypes.c_ulong), ('mmio_len', ctypes.c_uint32), ('accel', ctypes.c_uint32), ('reserved', ctypes.c_uint16 * 3), ]
[docs]class FbBitField(ctypes.Structure): """The fb_bitfield struct from fb.h.""" _fields_ = [ ('offset', ctypes.c_uint32), ('length', ctypes.c_uint32), ('msb_right', ctypes.c_uint32), ]
[docs]class VarScreenInfo(ctypes.Structure): """The fb_var_screeninfo struct from fb.h.""" _fields_ = [ ('xres', ctypes.c_uint32), ('yres', ctypes.c_uint32), ('xres_virtual', ctypes.c_uint32), ('yres_virtual', ctypes.c_uint32), ('xoffset', ctypes.c_uint32), ('yoffset', ctypes.c_uint32), ('bits_per_pixel', ctypes.c_uint32), ('grayscale', ctypes.c_uint32), ('red', FbBitField), ('green', FbBitField), ('blue', FbBitField), ('transp', FbBitField), ]
[docs]def open_fbdev(fbdev=None): """Return the framebuffer file descriptor. Try to use the FRAMEBUFFER environment variable if fbdev is not given. Use '/dev/fb0' by default. """ dev = fbdev or os.getenv('FRAMEBUFFER', '/dev/fb0') fbfid = FbFid(os.open(dev, os.O_RDWR)) fbfid.name = dev return fbfid
[docs]def close_fbdev(fbfid): """Close the framebuffer file descriptor.""" os.close(fbfid)
[docs]def get_fix_info(fbfid): """Return the fix screen info from the framebuffer file descriptor.""" fix_info = FixScreenInfo() ioctl(fbfid, FBIOGET_FSCREENINFO, fix_info) return fix_info
[docs]def get_var_info(fbfid): """Return the var screen info from the framebuffer file descriptor.""" var_info = VarScreenInfo() ioctl(fbfid, FBIOGET_VSCREENINFO, var_info) return var_info
[docs]def map_fb_memory(fbfid, fix_info): """Map the framebuffer memory.""" return mmap.mmap( fbfid, fix_info.smem_len, mmap.MAP_SHARED, mmap.PROT_READ | mmap.PROT_WRITE, offset=0 )
[docs]class FbMem(object): """The framebuffer memory object. Made of: - the framebuffer file descriptor - the fix screen info struct - the var screen info struct - the mapped memory """ __slots__ = ('fid', 'fix_info', 'var_info', 'mmap')
[docs]def open_fbmem(fbdev=None): """Create the FbMem framebuffer memory object.""" fid = open_fbdev(fbdev) fix_info = get_fix_info(fid) fbmmap = map_fb_memory(fid, fix_info) fbmem = FbMem() fbmem.fid = fid fbmem.fix_info = fix_info fbmem.var_info = get_var_info(fid) fbmem.mmap = fbmmap return fbmem
[docs]def memory_buffer(buffer_len): """Create a memory buffer of buffer_len size. this memory buffer can be used to create a custom cairo surface for double buffering (or n-buffering) :param int buffer_len: size of the buffer. :return: the created buffer """ _buffer = ctypes.create_string_buffer(buffer_len) return _buffer
[docs]def close_fbmem(fbmem): """Close the FbMem framebuffer memory object.""" fbmem.mmap.close() close_fbdev(fbmem.fid) # TODO: free the double_buffer ?
[docs]def cairo_surface_from_fbmem(fbmem, mem, cairo_format): """Create a cairo surface from FbMem object. :param fbmem: framebuffer memory object :param mem: the memory buffer, either created directly or via mmap :param int cairo_format: cairo pixel format. """ import cairocffi as cairo return cairo.ImageSurface.create_for_data( mem, cairo_format, # cairo.FORMAT_RGB24, # cairo.FORMAT_RGB16_565, etc... fbmem.var_info.xres, fbmem.var_info.yres, fbmem.fix_info.line_length)