驱动开发系列57 - Linux Graphics QXL显卡驱动代码分析(四)显示区域更新
一:概述
前面在介绍了显示模式设置(分辨率,刷新率)之后,本文继续分析下,显示区域的绘制,详细看看虚拟机的画面是如何由QXL显卡绘制出来的。
二:相关数据结构介绍
struct qxl_monitors_config {uint16_t count; // 当前启用的显示器数量(head 数量)uint16_t max_allowed; // 驱动允许的最大显示器数量,如果为 0,表示没有固定限制,由驱动动态决定struct qxl_head heads[]; // 每个显示器的配置数组(实际大小为 count)
};
struct qxl_head {uint32_t id; // 显示头(显示器)IDuint32_t surface_id; // 绑定的 QXLSurface IDuint32_t width; // 显示区域的宽度(像素)uint32_t height; // 显示区域的高度(像素)uint32_t x; // 在绑定 surface 上的 X 偏移(起始坐标)uint32_t y; // 在绑定 surface 上的 Y 偏移uint32_t flags; // 标志位,用于额外配置(比如是否启用、旋转等)
};
struct qxl_surface_id {uint32_t surface_id; // 表示 QXL 表面(Surface)的唯一标识符。每个表面都会有一个唯一的 ID,用于区分和识别不同的表面。
};
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;
};
struct qxl_image_descriptor {uint64_t id; // 图像的唯一标识符,用于标识该图像在系统中的位置uint8_t type; // 图像类型,用于指示该图像的具体格式或用途(例如位图、编码图像等)uint8_t flags; // 图像的标志位,通常用于表示图像的特定属性(例如是否是透明图像等)uint32_t width; // 图像的宽度,以像素为单位uint32_t height; // 图像的高度,以像素为单位
};
struct qxl_encoder_data {uint32_t data_size; // 编码数据的大小,单位是字节。uint8_t data[]; // 可变长度的编码数据,存储编码后的图像或图形数据。
};
struct qxl_palette {uint64_t unique; // 唯一标识符,用于区分不同的调色板。每个调色板都会有一个唯一的 ID。uint16_t num_ents; // 调色板条目的数量,即调色板中包含的颜色数。uint32_t ents[]; // 可变长度数组,存储调色板中的颜色值。每个条目代表一个颜色,通常是32位颜色值(例如 RGBA)。
};
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; // 图像数据的物理地址。指向存储位图像素数据的内存区域。
};
struct qxl_surface {uint32_t format; // 图形表面的格式(例如 RGBA,BGRA 等)uint32_t width; // 表面的宽度uint32_t height; // 表面的高度int32_t stride; // 行跨度,表示表面每行数据占用的字节数QXLPHYSICAL data; // 指向表面数据的物理地址
};
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;
};
struct qxl_clip_rects {uint32_t num_rects; // 包含的矩形数量struct qxl_data_chunk chunk; // 包含矩形数据的内容
};
struct qxl_drawable {// 释放信息,用于释放渲染资源时的管理union qxl_release_info release_info;// 该可绘制对象使用的表面IDuint32_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;
};
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 坐标(相对于光标左上角)
};
struct qxl_cursor {struct qxl_cursor_header header; // 光标的基本信息uint32_t data_size; // 光标数据的大小struct qxl_data_chunk chunk; // 包含光标数据的内容(例如:像素数据)
};
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 字节
};
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]; // 客户端能力,存储与虚拟机环境相关的信息
};
/* qxl-1 compat: append only */
struct qxl_rom {uint32_t magic; // 魔术数,用于验证这是一个有效的 QXL ROMuint32_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; // 客户端监视器配置,描述显示器的位置和尺寸
};