DRM -- FrameBuffer
Framebuffer 帧缓冲区是抽象的内存对象,提供了扫描到 CRTC 的像素源。应用程序通过 IOCTLDRM_IOCTL_MODE_ADDFB(2)来创建 framebuffer,会返回一个不透明句柄,该句柄可以传递给 KMS CRTC、来控制 plane configuration 和 page flip 功能。 数据结构 struct drm_framebuffer { struct drm_device *dev; struct list_head head; // framebuffer链表,可能有多个fb struct drm_mode_object base; char comm[TASK_COMM_LEN]; // allocate fb的进程名 const struct drm_format_info *format; // fb pixel format const struct drm_framebuffer_funcs *funcs; // 一行多少bytes, 会从用户空间的drm_mode_fb_cmd2拷贝过来 unsigned int pitches[DRM_FORMAT_MAX_PLANES]; // framebuffer和actual pixel data的offset,也从drm_mode_fb_cmd2拷贝过来 unsigned int offsets[DRM_FORMAT_MAX_PLANES]; uint64_t modifier; // 从drm_mode_fb_cmd2的modifier拷贝过来,DRM_FORMAT_MOD_XXX unsigned int width; // framebuffer宽 unsigned int height; // framebuffer高 int flags; // DRM_MODE_FB_INTERLACED, DRM_MODE_FB_MODIFIERS struct list_head filp_head; struct drm_gem_object *obj[DRM_FORMAT_MAX_PLANES]; }; struct drm_format_info { u32 format; // FOURCC格式,DRM_FORMAT_* u8 depth; // color depth, legacy field, 设置为0。 u8 num_planes; // Number of color planes (1 to 3) union { // 每个plane的bytes per pixel, legacy field。 u8 cpp[DRM_FORMAT_MAX_PLANES]; // 每个plane的bytes per block。用于单个pixel不是byte对齐的情况。 // block大小用下面的block_w和block_h来描述。 u8 char_per_block[DRM_FORMAT_MAX_PLANES]; }; u8 block_w[DRM_FORMAT_MAX_PLANES]; // block width占几个bytes u8 block_h[DRM_FORMAT_MAX_PLANES]; // block height占几个bytes u8 hsub; // 行采样因子 u8 vsub; // 列采样因子,比如yuv422那么hsub=2, vsub=1 bool has_alpha; // pixel format中是否含有alpha bool is_yuv; // 是不是yuv格式 bool is_color_indexed; // 是不是color_indexed格式,即伪彩,存index进color LUT查找对应颜色 }; struct drm_framebuffer_funcs { void (*destroy)(struct drm_framebuffer *framebuffer); int (*create_handle)(struct drm_framebuffer *fb, struct drm_file *file_priv, unsigned int *handle); // 有些硬件在fb内容更新后不会主动刷新内容到屏幕上。 // userspace需要通过DRM_IOCTL_MODE_DIRTYFB ioctl调用到dirty函数来刷新屏幕的某块区域。 int (*dirty)(struct drm_framebuffer *framebuffer, struct drm_file *file_priv, unsigned flags, unsigned color, struct drm_clip_rect *clips, unsigned num_clips); }; 注册 framebuffer 用户空间通过drmModeAddFB2()或drmModeAddFB2WithModifiers()函数来注册 framebuffer,需要传入struct drm_mode_fb_cmd2,除了fb_id是返回的参数,其他都是需要传入的参数:...