当前位置: 首页 > news >正文

驱动开发系列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;               // 客户端监视器配置,描述显示器的位置和尺寸
};

相关文章:

  • C#中从本地(两个路径文件夹)中实时拿图显示到窗口中并接收(两个tcp发送的信号)转为字符串显示在窗体中实现检测可视化
  • 【C语言】推箱子小游戏
  • C++ 构造函数
  • # YOLOv1:开启实时目标检测的新时代
  • tp8+swoole搭建
  • 如何提升丢包网络环境下的传输性能:从 TCP 到 QUIC,再到 wovenet 的实践
  • OpenGl实战笔记(2)基于qt5.15.2+mingw64+opengl实现纹理贴图
  • 【C++核心技术深度解析:从继承多态到STL容器 】
  • Nacos源码—4.Nacos集群高可用分析四
  • Python爬虫+代理IP+Header伪装:高效采集亚马逊数据
  • 【AI知识库云研发部署】RAGFlow + DeepSeek
  • python打卡day17
  • 解决android studio 中gradle 出现task list not built
  • 使用Unsloth微调DeepSeek-R1蒸馏模型:低显存高效训练实践
  • 效率提升利器:解锁图片处理新姿势
  • x-cmd install | Tuistash - Logstash 实时监控,告别图形界面,高效便捷!
  • 餐饮部绩效考核管理制度与综合评估方法
  • STL之stackqueue
  • Linux主机时间设置操作指南及时间异常影响
  • 开个帖子记录一下自己学spring源码的过程
  • 上海:5月8日起5年以上首套个人住房公积金贷款利率下调至2.6%
  • 国铁集团:铁路五一假期运输收官,多项运输指标创历史新高
  • 俄乌互相空袭、莫斯科机场关闭,外交部:当务之急是避免局势紧张升级
  • 潘功胜:降准0.5个百分点,降低政策利率0.1个百分点
  • 全军军级以上单位新任纪委书记监委主任培训班结业
  • 经济日报:落实落细更加积极的财政政策