Linux帧缓冲区像素位域通用实现

Posted

技术标签:

【中文标题】Linux帧缓冲区像素位域通用实现【英文标题】:Linux framebuffer pixel bitfield generic implementation 【发布时间】:2015-08-23 17:18:20 【问题描述】:

我正在编写一个小型库来与 Linux 的帧缓冲区抽象接口。我所有的显卡都使用相同的像素格式(每个通道一个八位字节,四个通道,BGRA 排序),到目前为止,库只采用这种格式。但是,如果我希望库在任何 Linux 帧缓冲区上工作,帧缓冲区 API 提供了我必须使用的像素格式数据。您不需要知道帧缓冲区是如何工作来回答这个问题的(我希望如此),只是一些我不精通的小技巧。这是我的标题中提供的像素格式信息:

/* Interpretation of offset for color fields: All offsets are from the right,
 * inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you
 * can use the offset as right argument to <<). A pixel afterwards is a bit
 * stream and is written to video memory as that unmodified.
 *
 * For pseudocolor: offset and length should be the same for all color
 * components. Offset specifies the position of the least significant bit
 * of the pallette index in a pixel value. Length indicates the number
 * of available palette entries (i.e. # of entries = 1 << length).
 */
struct fb_bitfield 
        __u32 offset;                   /* beginning of bitfield        */
        __u32 length;                   /* length of bitfield           */
        __u32 msb_right;                /* != 0 : Most significant bit is */ 
                                        /* right */
;

/* snip */

struct fb_var_screeninfo 
    /* snip */

        __u32 bits_per_pixel;           /* guess what                   */
        __u32 grayscale;                /* 0 = color, 1 = grayscale,    */
                                        /* >1 = FOURCC                  */
        struct fb_bitfield red;         /* bitfield in fb mem if true color, */
        struct fb_bitfield green;       /* else only length is significant */
        struct fb_bitfield blue;
        struct fb_bitfield transp;      /* transparency                 */      

        __u32 nonstd;                   /* != 0 Non standard pixel format */

    /* snip */
;

我需要将使用上述信息格式化的像素从四个字符(R、G、B 和 A)写入一个字符数组。我所做的错误尝试如下所示:

long pxl = 0;
/* downsample each channel to the length (assuming its less than 8 bits) */
/* with a right-shift, then left shift it over into place */
/* haven't done anything with fb_bitfield.msb_right */
pxl |= (r >> (8 - vinfo.red.length)) << vinfo.red.offset;
pxl |= (g >> (8 - vinfo.green.length)) << vinfo.green.offset;
pxl |= (b >> (8 - vinfo.blue.length)) << vinfo.blue.offset;
pxl |= (a >> (8 - vinfo.transp.length)) << vinfo.transp.offset;
fb[xy2off(x, y)] = /* umm... */;
/* little endian, big endian? Can I just assign here? */

xy2off 将坐标转换为索引。 fb 是指向帧缓冲区(内存映射)的指针。

谁能指出我转换和分配这些像素的正确方向?

【问题讨论】:

【参考方案1】:

亲爱的可能不存在的人正在寻找这个问题的答案:这是我现在似乎可以工作的黑客代码:

空像素(int x,int y,uint8_t r,uint8_t g,uint8_t b,uint8_t a)

    诠释我;
    长 pxl = 0;
    pxl |= (r >> (8 - vinfo.red.length)) > (8 - vinfo.green.length)) > (8 - vinfo.blue.length)) > (8 - vinfo.transp.length)) 

缺少字节序处理、处理 msb_right 或任何类型的优化。

【讨论】:

length=8 时有效。当长度> 8 时,您将右移负数位,这是 UB 或实现定义的,我不记得了。我猜你想做(r &gt;&gt; ( vinfo.red.length -8))。我也会避免使用long,而是使用intint32_tunsigned 会更好。 而您的fb[xy2off(x, y)] = 方式效率不高。一个很好的方法是*(uint32_t*)(fb+xy2off(x, y)) =pxl;,然后你可以用一条指令移动4个值,假设内存正确对齐。 fbchar * 所以你没有违反严格的别名规则。 感谢您的建议!如果您将其作为一个发布,我将接受您改进的答案 我们是否需要将其应用于帧缓冲区中的每个像素?有没有办法一次完成? @Diego Alonso Cortez 如果 C 允许您在运行时构建函数,那将是解决这个问题的一个优雅的解决方案。我的解决方案是为常见配置创建几个功能,如果没有匹配,则回退到这个。

以上是关于Linux帧缓冲区像素位域通用实现的主要内容,如果未能解决你的问题,请参考以下文章

通用帧缓冲区的当前方法?

如何从 OpenGL 中的帧缓冲区纹理中采样像素?

WebGL 帧缓冲区 ClearColor 仅影响 (0,0) 像素

帧缓存的详细介绍

基于鼠标单击读取帧缓冲区对象中的像素

我似乎无法修改帧缓冲区