驱动开发系列57 - Linux Graphics QXL显卡驱动代码分析(四)显示区域更新

一:概述

前面在介绍了显示模式设置(分辨率,刷新率)之后,本文继续分析下,显示区域的绘制,详细看看虚拟机的画面是如何由QXL显卡绘制出来的。

二:相关数据结构介绍

cpp 复制代码
struct qxl_monitors_config {
    uint16_t count;         // 当前启用的显示器数量(head 数量)
    uint16_t max_allowed;   // 驱动允许的最大显示器数量,如果为 0,表示没有固定限制,由驱动动态决定
    struct qxl_head heads[]; // 每个显示器的配置数组(实际大小为 count)
};
cpp 复制代码
struct qxl_head {
	uint32_t id;           // 显示头(显示器)ID
	uint32_t surface_id;   // 绑定的 QXLSurface ID
	uint32_t width;        // 显示区域的宽度(像素)
	uint32_t height;       // 显示区域的高度(像素)
	uint32_t x;            // 在绑定 surface 上的 X 偏移(起始坐标)
	uint32_t y;            // 在绑定 surface 上的 Y 偏移
	uint32_t flags;        // 标志位,用于额外配置(比如是否启用、旋转等)
};
cpp 复制代码
struct qxl_surface_id {
    uint32_t surface_id; // 表示 QXL 表面(Surface)的唯一标识符。每个表面都会有一个唯一的 ID,用于区分和识别不同的表面。
};
cpp 复制代码
struct qxl_image {
    struct qxl_image_descriptor descriptor;  // 图像的描述符,包含图像的基本信息(例如图像类型、大小等)
    union {  /* 可变长度的数据,根据图像类型选择使用 */
        struct qxl_bitmap bitmap;        // 图像数据,作为位图(bitmap)表示
        struct qxl_encoder_data quic;    // 图像数据,作为 QUIC 编码数据表示(用于高效传输)
        struct qxl_surface_id surface_image; // 图像数据,作为表面图像的 ID 表示(指向一个渲染表面)
    } u;
};
cpp 复制代码
struct qxl_image_descriptor {
    uint64_t id;           // 图像的唯一标识符,用于标识该图像在系统中的位置
    uint8_t type;          // 图像类型,用于指示该图像的具体格式或用途(例如位图、编码图像等)
    uint8_t flags;         // 图像的标志位,通常用于表示图像的特定属性(例如是否是透明图像等)
    uint32_t width;        // 图像的宽度,以像素为单位
    uint32_t height;       // 图像的高度,以像素为单位
};
cpp 复制代码
struct qxl_encoder_data {
    uint32_t data_size;   // 编码数据的大小,单位是字节。
    uint8_t data[];       // 可变长度的编码数据,存储编码后的图像或图形数据。
};
cpp 复制代码
struct qxl_palette {
    uint64_t unique;      // 唯一标识符,用于区分不同的调色板。每个调色板都会有一个唯一的 ID。
    uint16_t num_ents;    // 调色板条目的数量,即调色板中包含的颜色数。
    uint32_t ents[];      // 可变长度数组,存储调色板中的颜色值。每个条目代表一个颜色,通常是32位颜色值(例如 RGBA)。
};
cpp 复制代码
struct qxl_bitmap {
    uint8_t format;        // 位图的格式,表示图像数据的颜色深度或编码方式。
    uint8_t flags;         // 位图的标志字段,指示位图的附加属性或状态。
    uint32_t x;            // 位图的 X 坐标,表示位图左上角的位置。
    uint32_t y;            // 位图的 Y 坐标,表示位图左上角的位置。
    uint32_t stride;       // 位图每行的字节数,即图像数据的跨度。用于访问像素数据时的步长。
    QXLPHYSICAL palette;   // 调色板的物理地址,用于与调色板相关的数据。通常这是指向 `qxl_palette` 结构体的指针。
    QXLPHYSICAL data;      // 图像数据的物理地址。指向存储位图像素数据的内存区域。
};
cpp 复制代码
struct qxl_surface {
    uint32_t format;      // 图形表面的格式(例如 RGBA,BGRA 等)
    uint32_t width;       // 表面的宽度
    uint32_t height;      // 表面的高度
    int32_t stride;       // 行跨度,表示表面每行数据占用的字节数
    QXLPHYSICAL data;     // 指向表面数据的物理地址
};
cpp 复制代码
struct qxl_surface_cmd {
    union qxl_release_info release_info;  // 用于释放的额外信息
    uint32_t surface_id;                  // 表面ID,标识一个具体的图形表面
    uint8_t type;                         // 命令类型,指示是创建表面还是销毁表面
    uint32_t flags;                       // 命令标志,可能用于控制命令的行为
    union {
        struct qxl_surface surface_create;  // 创建表面时的相关信息
    } u;
};
cpp 复制代码
struct qxl_clip_rects {
    uint32_t num_rects;       // 包含的矩形数量
    struct qxl_data_chunk chunk;  // 包含矩形数据的内容
};
cpp 复制代码
struct qxl_drawable {
    // 释放信息,用于释放渲染资源时的管理
    union qxl_release_info release_info;

    // 该可绘制对象使用的表面ID
    uint32_t surface_id;

    // 绘制效果类型,用于标识渲染操作的效果类型(例如:透明、混合等)
    uint8_t effect;

    // 绘制对象类型,定义该对象的类型(例如:填充、文本、复制等)
    uint8_t type;

    // 标记是否是自带位图数据,如果是,则会直接使用该位图
    uint8_t self_bitmap;

    // 如果是自带位图,定义位图的有效区域
    struct qxl_rect self_bitmap_area;

    // 可绘制对象的边界框,定义了渲染的边界范围
    struct qxl_rect bbox;

    // 裁剪区域,定义了在渲染时应考虑的区域,超出该区域的部分将被裁剪掉
    struct qxl_clip clip;

    // 内存管理时间戳,用于标识该对象的渲染时间
    uint32_t mm_time;

    // 目标表面数组,最多支持三个目标表面
    int32_t surfaces_dest[3];

    // 每个目标表面的渲染区域矩形
    struct qxl_rect surfaces_rects[3];

    // 根据绘制类型选择不同的绘制操作,这里使用联合体来支持多种操作
    union {
        // 填充操作,例如使用颜色填充区域
        struct qxl_fill fill;
        
        // 不透明操作,可能表示不透明的填充区域
        struct qxl_opaque opaque;
        
        // 复制操作,将源区域复制到目标区域
        struct qxl_copy copy;
        
        // 透明操作,可能表示透明背景或区域
        struct qxl_transparent transparent;
        
        // alpha混合操作,支持透明度的混合效果
        struct qxl_alpha_blend alpha_blend;
        
        // 复制位图操作,支持特定的位图复制
        struct qxl_copy_bits copy_bits;
        
        // 复制操作的另一种形式
        struct qxl_copy blend;
        
        // 3元逻辑操作,用于图像处理中基于位的像素操作
        struct qxl_rop_3 rop3;
        
        // 描边操作,用于绘制路径的边框
        struct qxl_stroke stroke;
        
        // 文本渲染操作,用于绘制文本
        struct qxl_text text;
        
        // 黑色掩码操作,支持黑色掩码效果
        struct qxl_mask blackness;
        
        // 反转掩码操作,用于像素的反色效果
        struct qxl_mask invers;
        
        // 白色掩码操作,支持白色掩码效果
        struct qxl_mask whiteness;
        
        // 合成操作,用于合成多个图像层
        struct qxl_composite composite;
    } u;
};
cpp 复制代码
struct qxl_cursor_header {
    uint64_t unique;          // 唯一标识符,标识一个光标
    uint16_t type;            // 光标类型(例如:标准光标、自定义光标)
    uint16_t width;           // 光标的宽度(以像素为单位)
    uint16_t height;          // 光标的高度(以像素为单位)
    uint16_t hot_spot_x;      // 热点位置的 X 坐标(相对于光标左上角)
    uint16_t hot_spot_y;      // 热点位置的 Y 坐标(相对于光标左上角)
};
cpp 复制代码
struct qxl_cursor {
    struct qxl_cursor_header header;  // 光标的基本信息
    uint32_t data_size;              // 光标数据的大小
    struct qxl_data_chunk chunk;     // 包含光标数据的内容(例如:像素数据)
};
cpp 复制代码
struct qxl_cursor_cmd {
    union qxl_release_info release_info;  // 释放信息,用于同步或更新
    uint8_t type;                         // 光标操作类型(例如:设置、移动、隐藏)
    union {
        struct {  
            struct qxl_point_1_6 position;   // 光标的新位置
            uint8_t visible;                 // 光标是否可见
            QXLPHYSICAL shape;               // 光标形状数据
        } set;                              // 设置光标操作
        struct {  
            uint16_t length;                 // 光标轨迹的长度
            uint16_t frequency;              // 光标轨迹的频率
        } trail;                            // 设置光标轨迹操作
        struct qxl_point_1_6 position;      // 光标的新位置(在移动或其他命令中使用)
    } u;
    uint8_t device_data[QXL_CURSOR_DEVICE_DATA_SIZE];  // 设备特定数据,大小为 128 字节
};
cpp 复制代码
struct qxl_ram_header {
    uint32_t magic;                            // 魔术数字,用于验证数据结构是否正确
    uint32_t int_pending;                      // 当前挂起的中断
    uint32_t int_mask;                         // 中断屏蔽
    uint8_t log_buf[QXL_LOG_BUF_SIZE];         // 日志缓冲区,用于记录日志
    struct qxl_ring_header cmd_ring_hdr;       // 命令环头,用于管理命令队列
    struct qxl_command cmd_ring[QXL_COMMAND_RING_SIZE]; // 命令环,用于存储具体的命令
    struct qxl_ring_header cursor_ring_hdr;    // 光标环头,用于管理光标队列
    struct qxl_command cursor_ring[QXL_CURSOR_RING_SIZE]; // 光标环,用于存储光标命令
    struct qxl_ring_header release_ring_hdr;   // 释放环头,用于管理释放命令
    uint64_t release_ring[QXL_RELEASE_RING_SIZE]; // 释放环,用于存储释放命令
    struct qxl_rect update_area;               // 更新区域,表示图形更新的区域
    /* appended for qxl-2 */
    uint32_t update_surface;                   // 更新的表面 ID,用于指定目标表面
    struct qxl_mem_slot mem_slot;              // 内存槽,用于分配图形内存
    struct qxl_surface_create create_surface;  // 表面创建结构,表示新创建的图形表面
    uint64_t flags;                            // 标志位,用于存储相关的配置信息

    /* appended for qxl-4 */
    /* used by QXL_IO_MONITORS_CONFIG_ASYNC */
    QXLPHYSICAL monitors_config;               // 显示器配置,用于存储显示器相关的配置信息
    uint8_t guest_capabilities[64];            // 客户端能力,存储与虚拟机环境相关的信息
};
cpp 复制代码
/* qxl-1 compat: append only */
struct qxl_rom {
    uint32_t magic;                         // 魔术数,用于验证这是一个有效的 QXL ROM
    uint32_t id;                            // ROM 的唯一标识符
    uint32_t update_id;                     // 更新标识符,用于标记 ROM 版本或更新次数
    uint32_t compression_level;             // 压缩级别,可能指示 ROM 数据的压缩程度
    uint32_t log_level;                     // 日志级别,控制 QXL 驱动的日志输出详细程度
    uint32_t mode;                          // 驱动的工作模式(qxl-1 特定)
    uint32_t modes_offset;                  // 显示模式的偏移量,指向模式数据的位置
    uint32_t num_io_pages;                  // I/O 页的数量,表示 ROM 中的 I/O 页数量
    uint32_t pages_offset;                  // 页面的偏移量,指向页面数据的位置(qxl-1 特定)
    uint32_t draw_area_offset;              // 绘制区域的偏移量,表示绘制区域在 ROM 中的位置(qxl-1 特定)
    uint32_t surface0_area_size;            // 表面0区域的大小,用于描述第一个图形表面的内存大小(qxl-1 特定,名为 draw_area_size)
    uint32_t ram_header_offset;             // RAM 头部的偏移量,指向 RAM 头部数据的位置
    uint32_t mm_clock;                      // 内存时钟频率,控制 RAM 访问的时序,影响性能

    /* qxl-2 特有字段 */
    uint32_t n_surfaces;                   // 表面数量,表示支持的图形表面数量
    uint64_t flags;                         // 标志位,存储驱动的配置特性
    uint8_t slots_start;                    // 起始槽位,内存槽位的起始位置
    uint8_t slots_end;                      // 结束槽位,内存槽位的结束位置
    uint8_t slot_gen_bits;                  // 槽生成位数,用于标识槽位的生成位
    uint8_t slot_id_bits;                   // 槽 ID 位数,表示槽位的唯一标识符的位数
    uint8_t slot_generation;                // 槽代号,用于表示槽位的代次(内存管理、版本控制)

    /* qxl-4 特有字段 */
    uint8_t client_present;                 // 客户端存在标志,指示客户端是否存在
    uint8_t client_capabilities[58];        // 客户端的能力位图,描述客户端支持的功能或特性
    uint32_t client_monitors_config_crc;    // 客户端显示配置的 CRC 校验和,用于验证配置的有效性
    struct {
        uint16_t count;                     // 显示器配置的数量
        uint16_t padding;                   // 填充,保持对齐
        struct qxl_urect heads[64];         // 显示器配置,最多支持 64 个显示器
    } client_monitors_config;               // 客户端监视器配置,描述显示器的位置和尺寸
};
相关推荐
sukalot1 天前
window 显示驱动开发-线程和同步级别为零级
java·开发语言·驱动开发
狄加山6751 天前
I2C总线驱动开发:MPU6050应用
驱动开发
Blossom.1182 天前
脑机接口技术:开启人类与机器的全新交互时代
人工智能·驱动开发·深度学习·计算机视觉·aigc·硬件架构·交互
程序员JerrySUN3 天前
驱动开发硬核特训 · Day 24(下篇):深入理解 Linux 内核时钟子系统结构
linux·运维·驱动开发
__Benco3 天前
OpenHarmony平台驱动开发(二),CLOCK
人工智能·驱动开发·harmonyos
程序员JerrySUN3 天前
驱动开发硬核特训 · Day 27(上篇):Linux 内核子系统的特性全解析
linux·运维·驱动开发
程序员JerrySUN3 天前
驱动开发硬核特训 · Day 27(下篇):深入掌握 Common Clock Framework 架构与实战开发
驱动开发·架构
__Benco3 天前
OpenHarmony平台驱动开发(一),ADC
人工智能·驱动开发·harmonyos
南棱笑笑生5 天前
20250502在ubuntu18.04.6系统上编译RK3566的buildroot系统【linux-4.19内核】
驱动开发